ModelChoiceField does not show ForeignKey choices

Viewed 229

I want to show a dropdown in Django Form where the dropdown items are specified in another model in another app. Here's what I mean:

title/models.py

TITLE_CHOICES = (
    ('MR', 'Mr'),
    ('MS', 'Ms'),
    ('MISS', 'Miss'),
    ('MRS', 'Mrs'),
    ('MX', 'Mx'),
)

class Title(models.Model):
    title_name = models.CharField(max_length=10, choices=TITLE_CHOICES)

    def __str__(self):
        return self.title_name

user/models.py

class User(models.Model):
    ...
    user_title = models.ForeignKey('title.Title', on_delete=models.CASCADE)
    ...

user/forms.py

class SignupForm(forms.ModelForm):
        user_title = forms.ModelChoiceField(queryset=Title.objects.all())

        class Meta:
            model = User
            fields = '__all__'

        def signup(self, request, user): #this is to override the **allauth** signup form
            user.user_title = self.cleaned_data['title_name']
            ...
            ...

            user.save()

With the above code, the dropdown field renders properly; however, it is empty. enter image description here

Any ideas or suggestions are greatly appreciated.

Thanks.

3 Answers

Please change your user_title field to this and Try this.

user_title = forms.ModelChoiceField(queryset=Title.objects.all(), widget=forms.Select(attrs={'class': 'form-control'}))

If you are going to create all of the choices in TITLE_CHOICES you declared, I would just make a fixture and load it to database.

I would change the model a bit: title.models

def Title(models.Model):
    title_name = models.CharField(max_length=10)
    title = models.CharField(max_length=10)

    def __str__(self):
        return self.title_name

then make a json file: title/fixtures/titles.json

[
    {
        "model": "title.Title",
        "pk": 1,
        "fields": {
          "title_name": "MR",
          "title" : "Mr"
        }
    },
    {
        "model": "title.Title",
        "pk": 2,
        "fields": {
          "title_name": "MS",
          "title" : "Ms"
        }
    },
    ...
]

Then load this json file to database by python manage.py loaddata titles command. This will automatically create all instances in json file to database.

Note that you have to save the file in a folder named fixtures otherwise it returns error.

Now while creating the user you will get the Title ForeignKey will show the title_name in options list instead of the title.

user_title = forms.ModelChoiceField(queryset=Title.objects.all(), flat=True)
Related