[1.8.x] Fixed #24958 -- Fixed inline forms using UUID-PK parents with auto-PK children.

Backport of a50b66da30 from master
This commit is contained in:
Jason Hoos 2015-06-05 15:04:24 -05:00 committed by Tim Graham
parent a97e50c5e6
commit 4296801463
4 changed files with 89 additions and 4 deletions

View File

@ -922,10 +922,15 @@ class BaseInlineFormSet(BaseModelFormSet):
if self.fk.rel.field_name != self.fk.rel.to._meta.pk.name: if self.fk.rel.field_name != self.fk.rel.to._meta.pk.name:
kwargs['to_field'] = self.fk.rel.field_name kwargs['to_field'] = self.fk.rel.field_name
# If we're adding a new object, ignore a parent's auto-generated pk # If we're adding a new object, ignore a parent's auto-generated key
# as it will be regenerated on the save request. # as it will be regenerated on the save request.
if self.instance._state.adding and form._meta.model._meta.pk.has_default(): if self.instance._state.adding:
self.instance.pk = None if kwargs.get('to_field') is not None:
to_field = self.instance._meta.get_field(kwargs['to_field'])
else:
to_field = self.instance._meta.pk
if to_field.has_default():
setattr(self.instance, to_field.attname, None)
form.fields[name] = InlineForeignKeyField(self.instance, **kwargs) form.fields[name] = InlineForeignKeyField(self.instance, **kwargs)

View File

@ -85,3 +85,7 @@ Bugfixes
* Reallowed non-ASCII values for ``ForeignKey.related_name`` on Python 3 by * Reallowed non-ASCII values for ``ForeignKey.related_name`` on Python 3 by
fixing the false positive system check (:ticket:`25016`). fixing the false positive system check (:ticket:`25016`).
* Fixed inline forms that use a parent object that has a ``UUIDField`` primary
key and a child object that has an ``AutoField`` primary key
(:ticket:`24958`).

View File

@ -254,3 +254,33 @@ class UUIDPKChild(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
parent = models.ForeignKey(UUIDPKParent) parent = models.ForeignKey(UUIDPKParent)
class ChildWithEditablePK(models.Model):
name = models.CharField(max_length=255, primary_key=True)
parent = models.ForeignKey(UUIDPKParent)
class AutoPKChildOfUUIDPKParent(models.Model):
name = models.CharField(max_length=255)
parent = models.ForeignKey(UUIDPKParent)
class AutoPKParent(models.Model):
name = models.CharField(max_length=255)
class UUIDPKChildOfAutoPKParent(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=255)
parent = models.ForeignKey(AutoPKParent)
class ParentWithUUIDAlternateKey(models.Model):
uuid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=50)
class ChildRelatedViaAK(models.Model):
name = models.CharField(max_length=255)
parent = models.ForeignKey(to=ParentWithUUIDAlternateKey, to_field='uuid')

View File

@ -1,7 +1,11 @@
from django.forms.models import inlineformset_factory from django.forms.models import inlineformset_factory
from django.test import TestCase from django.test import TestCase
from .models import UUIDPKChild, UUIDPKParent from .models import (
AutoPKChildOfUUIDPKParent, AutoPKParent, ChildRelatedViaAK,
ChildWithEditablePK, ParentWithUUIDAlternateKey, UUIDPKChild,
UUIDPKChildOfAutoPKParent, UUIDPKParent,
)
class InlineFormsetTests(TestCase): class InlineFormsetTests(TestCase):
@ -10,6 +14,8 @@ class InlineFormsetTests(TestCase):
#24377 - If we're adding a new object, a parent's auto-generated pk #24377 - If we're adding a new object, a parent's auto-generated pk
from the model field default should be ignored as it's regenerated on from the model field default should be ignored as it's regenerated on
the save request. the save request.
Tests the case where both the parent and child have a UUID primary key.
""" """
FormSet = inlineformset_factory(UUIDPKParent, UUIDPKChild, fields='__all__') FormSet = inlineformset_factory(UUIDPKParent, UUIDPKChild, fields='__all__')
formset = FormSet() formset = FormSet()
@ -30,3 +36,43 @@ class InlineFormsetTests(TestCase):
'uuidpkchild_set-2-name': '', 'uuidpkchild_set-2-name': '',
}) })
self.assertTrue(formset.is_valid()) self.assertTrue(formset.is_valid())
def test_inlineformset_factory_nulls_default_pks_uuid_parent_auto_child(self):
"""
#24958 - Variant of test_inlineformset_factory_nulls_default_pks for
the case of a parent object with a UUID primary key and a child object
with an AutoField primary key.
"""
FormSet = inlineformset_factory(UUIDPKParent, AutoPKChildOfUUIDPKParent, fields='__all__')
formset = FormSet()
self.assertIsNone(formset.forms[0].fields['parent'].initial)
def test_inlineformset_factory_nulls_default_pks_auto_parent_uuid_child(self):
"""
#24958 - Variant of test_inlineformset_factory_nulls_default_pks for
the case of a parent object with an AutoField primary key and a child
object with a UUID primary key.
"""
FormSet = inlineformset_factory(AutoPKParent, UUIDPKChildOfAutoPKParent, fields='__all__')
formset = FormSet()
self.assertIsNone(formset.forms[0].fields['parent'].initial)
def test_inlineformset_factory_nulls_default_pks_child_editable_pk(self):
"""
#24958 - Variant of test_inlineformset_factory_nulls_default_pks for
the case of a parent object with a UUID primary key and a child
object with an editable natural key for a primary key.
"""
FormSet = inlineformset_factory(UUIDPKParent, ChildWithEditablePK, fields='__all__')
formset = FormSet()
self.assertIsNone(formset.forms[0].fields['parent'].initial)
def test_inlineformset_factory_nulls_default_pks_alternate_key_relation(self):
"""
#24958 - Variant of test_inlineformset_factory_nulls_default_pks for
the case of a parent object with a UUID alternate key and a child
object that relates to that alternate key.
"""
FormSet = inlineformset_factory(ParentWithUUIDAlternateKey, ChildRelatedViaAK, fields='__all__')
formset = FormSet()
self.assertIsNone(formset.forms[0].fields['parent'].initial)