Opened 4 years ago
Last modified 4 years ago
#32432 closed Bug
ModelForm does not respect ModelChoiceField's to_field_name attribute — at Initial Version
Reported by: | gopackgo90 | Owned by: | nobody |
---|---|---|---|
Component: | Forms | Version: | 3.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
This is the same issue mentioned in #17657 but for ModelChoiceField instead of ModelMultipleChoiceField. This bug is present in Django 2.2.18 and Django 3.1.6. The first two tests were taken directly from #17657 just to show that ModelMultipleChoiceField still works as expected and the equivalent ModelChoiceField tests are added after, the last of which fails:
# models.py from django.db import models class Foo(models.Model): slug = models.CharField(max_length=40, unique=True) title = models.CharField(max_length=40, unique=True) def __str__(self): return self.title class Bar(models.Model): foos = models.ManyToManyField(Foo) class Baz(models.Model): foo = models.ForeignKey(Foo, on_delete=models.CASCADE)
# tests.py from django.test.testcases import TestCase from django import forms from .models import Foo, Bar, Baz class TestModelRelationshipChoiceWithFieldName(TestCase): @classmethod def setUpTestData(cls): spam = Foo.objects.create(title="Spam", slug="spam") ham = Foo.objects.create(title="Ham", slug="ham") eggs = Foo.objects.create(title="Eggs", slug="eggs") cls.m2m_instance = Bar.objects.create() cls.m2m_instance.foos.add(spam) cls.m2m_instance.foos.add(ham) cls.m2m_instance.foos.add(eggs) cls.fk_instance = Baz.objects.create(foo=eggs) def test_multiple_without_field_name(self): class Form(forms.ModelForm): foos = forms.ModelMultipleChoiceField(Foo.objects.all()) class Meta: model = Bar fields = '__all__' form = Form(instance=self.m2m_instance) self.assertEquals( str(form["foos"]), '<select name="foos" required id="id_foos" multiple>\n' ' <option value="1" selected>Spam</option>\n\n' ' <option value="2" selected>Ham</option>\n\n' ' <option value="3" selected>Eggs</option>\n\n' '</select>' ) def test_multiple_with_field_name(self): class Form(forms.ModelForm): foos = forms.ModelMultipleChoiceField(Foo.objects.all(), to_field_name="slug") class Meta: model = Bar fields = '__all__' form = Form(instance=self.m2m_instance) # Fixed in #17657, options weren't selected. self.assertEquals( str(form["foos"]), '<select name="foos" required id="id_foos" multiple>\n' ' <option value="spam" selected>Spam</option>\n\n' ' <option value="ham" selected>Ham</option>\n\n' ' <option value="eggs" selected>Eggs</option>\n\n' '</select>' ) def test_one_without_field_name(self): class Form(forms.ModelForm): foo = forms.ModelChoiceField(Foo.objects.all()) class Meta: model = Baz fields = '__all__' form = Form(instance=self.fk_instance) self.assertEquals( str(form["foo"]), '<select name="foo" required id="id_foo">\n' ' <option value="">---------</option>\n\n' ' <option value="1">Spam</option>\n\n' ' <option value="2">Ham</option>\n\n' ' <option value="3" selected>Eggs</option>\n\n' '</select>' ) def test_one_with_field_name(self): class Form(forms.ModelForm): foo = forms.ModelChoiceField(Foo.objects.all(), to_field_name="slug") class Meta: model = Baz fields = '__all__' form = Form(instance=self.fk_instance) # Fails! Option isn't selected. self.assertEquals( str(form["foo"]), '<select name="foo" required id="id_foo">\n' ' <option value="">---------</option>\n\n' ' <option value="spam">Spam</option>\n\n' ' <option value="ham">Ham</option>\n\n' ' <option value="eggs" selected>Eggs</option>\n\n' '</select>' )
Note:
See TracTickets
for help on using tickets.