I'm trying to made a modelform with a modelchoicewidget which inherits its choices from another model than the model the modelform is connected to, and this selection is to be filtered by the current logged in user. The example below illustrates my intentions - let's say I have two different models where one model allows the user to register meal types (breakfast, dinner etc), and the other model allows the user to create specific meals based on those meal types, with the connecting variable being the title of the meal type.
models.py:
class Mealtypes(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200, default='')
description = models.TextField(default='')
class Specificmeals(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
meal_name = models.CharField(max_length=200, default='')
mealtype = models.CharField(max_length=200, default='')
fruit = models.BooleanField(default=False)
meat = models.BooleanField(default=False)
dairy = models.BooleanField(default=False)
forms.py
from django import forms
from django.core.exceptions import ValidationError
from django.forms import ModelForm
from .models import Mealtypes, Specificmeals
class MealAdder(ModelForm):
class Meta:
model = Specificmeals
fields = [
'meal_name',
'mealtype',
'fruit',
'meat',
'dairy',
]
widgets = {
'text': forms.Textarea(attrs={"style": "height:10em;" "width:60em;"}),
'mealtype': forms.ModelChoiceField(queryset=Mealtypes.title.filter(author='author')),
'fruit': forms.CheckboxInput(attrs={"style": "margin-left:350px;"}),
'meat': forms.CheckboxInput(attrs={"style": "margin-left:350px;"}),
'dairy': forms.CheckboxInput(attrs={"style": "margin-left:350px;"}),
}
I'm trying to play around with the ModelChoiceField to make it query the mealtypes from the Mealtypes model filtered by the current user, but I keep getting attribute errors (object has no attribute..)
What am I doing wrong, and how can I solve this?
CodePudding user response:
First, add the following to your Mealtype
model, so you can output the actual title of the MealType:
def __str__(self):
return f"{self.title}"
Then, start by passing the request user in your view:
form = MealAdder(author=request.user)
And then in your forms.py
you should use the queryset in the form's __init__
like the following:
from django.forms import TextInput, CheckboxInput, Select, ModelChoiceField
class MealAdder(ModelForm):
def __init__(self, author, *args, **kwargs):
super(MealAdder, self).__init__(*args, **kwargs)
self.fields['mealtype'] = forms.ModelChoiceField(queryset=Mealtypes.objects.filter(author=author))
class Meta:
model = Specificmeals
fields = ['author', 'meal_name', 'mealtype', 'fruit', 'meat', 'dairy']
widgets = {
'author': Select(),
'meal_name': TextInput(attrs={"style": "height:10em;" "width:60em;"}),
'fruit': CheckboxInput(attrs={"style": "margin-left:350px;"}),
'meat': CheckboxInput(attrs={"style": "margin-left:350px;"}),
'dairy': CheckboxInput(attrs={"style": "margin-left:350px;"})
}
Don't forget you have to have an author
field in the form, as this cannot be null.