[Django] #32432: ModelForm does not respect ModelChoiceField's to_field_name attribute

67 views
Skip to first unread message

Django

unread,
Feb 8, 2021, 12:03:59 PM2/8/21
to django-...@googlegroups.com
#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.

Django

unread,
Feb 8, 2021, 12:15:54 PM2/8/21
to django-...@googlegroups.com
#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 | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Description changed by gopackgo90:

Old description:

New 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:


{{{#!python
# 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)
}}}


{{{#!python
# tests.py


class TestModelRelationshipChoiceWithFieldName(TestCase):

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())

form = Form(instance=self.m2m_instance)

def test_multiple_with_field_name(self):

class Form(forms.ModelForm):

form = Form(instance=self.m2m_instance)

def test_one_without_field_name(self):

class Form(forms.ModelForm):

foo = forms.ModelChoiceField(Foo.objects.all())

form = Form(instance=self.fk_instance)

def test_one_with_field_name(self):

class Form(forms.ModelForm):

form = Form(instance=self.fk_instance)

--

--
Ticket URL: <https://code.djangoproject.com/ticket/32432#comment:1>

Django

unread,
Feb 8, 2021, 1:42:39 PM2/8/21
to django-...@googlegroups.com
#32432: ModelForm does not respect ModelChoiceField's to_field_name attribute
----------------------------+--------------------------------------
Reporter: gopackgo90 | Owner: nobody
Type: Bug | Status: closed
Component: Forms | Version: 3.1
Severity: Normal | Resolution: duplicate

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+--------------------------------------
Changes (by Mariusz Felisiak):

* status: new => closed
* type: Uncategorized => Bug
* resolution: => duplicate


Comment:

Duplicate of #28316.

--
Ticket URL: <https://code.djangoproject.com/ticket/32432#comment:2>

Reply all
Reply to author
Forward
0 new messages