[Django] #34084: Regression in Django 4.1 so ModelForms always set self.instance even when none passed in

6 views
Skip to first unread message

Django

unread,
Oct 11, 2022, 1:28:19 PM10/11/22
to django-...@googlegroups.com
#34084: Regression in Django 4.1 so ModelForms always set self.instance even when
none passed in
-------------------------------------+-------------------------------------
Reporter: Steven | Owner: nobody
Mapes |
Type: Bug | Status: new
Component: Database | Version: 4.1
layer (models, ORM) |
Severity: Normal | Keywords: modelform
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
I came across this bug this morning when running my testsuite against
Django 3.2, 4.0 and 4.1 (4.1.0, 4.1.1 and 4.1.2). The issue is with
ModelForms when they are used without passing in an existing saved
instance. I thought this was related to the regression that was then fixed
in 4.1.2 and mentioned in both
[https://code.djangoproject.com/ticket/33984 33984] and
[https://code.djangoproject.com/ticket/33952 33952] but the issue is still
occurring even though both of those are closed.

To test you can use the below models, form and unit test

{{{
# models.py
from django.db import models


class Tag(models.Model):
tag = models.SlugField(max_length=64, unique=True)


class Thing(models.Model):
tag = models.ForeignKey(Tag, on_delete=models.CASCADE,
related_name="things")
active = models.BooleanField(default=True)

}}}

{{{
# forms.py
from django import forms
from example.models import Tag


class TagForm(forms.ModelForm):
class Meta:
model = Tag
fields = ["tag"]

def __init__(self, *args, **kwargs):
super(TagForm, self).__init__(*args, **kwargs)

if self.instance and self.instance.things:
inactive_things = self.instance.things.filter(active=False)
# Do something with it

}}}


{{{
from unittest.case import TestCase
from example.forms import TagForm


class TagFormCase(TestCase):
def test_required(self):
"""Test required fields"""
form = TagForm({})
self.assertFalse(form.is_valid())
self.assertEqual(
{
"tag": ["This field is required."],
},
form.errors,
)


}}}

If you run the test on Django versions <4.1 including Django 2.*, Django
3.* and 4.0.* then it'll pass but on 4.1.* it'll fail with ```ValueError:
'Tag' instance needs to have a primary key value before this relationship
can be used.```

In order to pass the if statement needs to be changed to ```if
self.instance.pk and self.instance.things``` as self.instance is no longer
None if no instance is passed in.

If your model uses a custom primary key such as a uuid4 then it'll work as
expected as the uuid4 is already called

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

Django

unread,
Oct 11, 2022, 1:31:25 PM10/11/22
to django-...@googlegroups.com
#34084: Regression in Django 4.1 so ModelForms always set self.instance even when
none passed in
------------------------------+--------------------------------------
Reporter: Steven Mapes | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 4.1
Severity: Normal | Resolution:
Keywords: modelform | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+--------------------------------------
Changes (by Steven Mapes):

* component: Database layer (models, ORM) => Forms


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

Django

unread,
Oct 11, 2022, 9:59:49 PM10/11/22
to django-...@googlegroups.com
#34084: Regression in Django 4.1 so ModelForms always set self.instance even when
none passed in
------------------------------+--------------------------------------
Reporter: Steven Mapes | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 4.1
Severity: Normal | Resolution:
Keywords: modelform | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+--------------------------------------
Changes (by David Kwong):

* cc: David Kwong (added)


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

Reply all
Reply to author
Forward
0 new messages