#32432: ModelForm does not respect ModelChoiceField's to_field_name attribute
-----------------------------------------+------------------------
               Reporter:  gopackgo90     |          Owner:  nobody
                   Type:  Uncategorized  |         Status:  new
              Component:  Forms          |        Version:  3.1
               Severity:  Normal         |       Keywords:
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  0              |
-----------------------------------------+------------------------
 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>'
         )
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/32432>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/053.e7e87998dfb5cc377c04af9cd7695b23%40djangoproject.com.

Reply via email to