Home > Software design >  Django - How to populate choices in a modelchoicefield with a field from another model filtered by l
Django - How to populate choices in a modelchoicefield with a field from another model filtered by l

Time:11-03

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.

  • Related