Skip to content

Commit 53fb45c

Browse files
committed
Fixed django#17615 -- Corrected unique field validation when using multitable inheritance. The validation used wrong pk value if the parent and child model had different pk fields. Thanks ungenio for the report and patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17920 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 3d5d0be commit 53fb45c

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

django/db/models/base.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,9 +718,13 @@ def _perform_unique_checks(self, unique_checks):
718718

719719
# Exclude the current object from the query if we are editing an
720720
# instance (as opposed to creating a new one)
721-
if not self._state.adding and self.pk is not None:
722-
qs = qs.exclude(pk=self.pk)
723-
721+
# Note that we need to use the pk as defined by model_class, not
722+
# self.pk. These can be different fields because model inheritance
723+
# allows single model to have effectively multiple primary keys.
724+
# Refs #17615.
725+
model_class_pk = self._get_pk_val(model_class._meta)
726+
if not self._state.adding and model_class_pk is not None:
727+
qs = qs.exclude(pk=model_class_pk)
724728
if qs.exists():
725729
if len(unique_check) == 1:
726730
key = unique_check[0]

tests/regressiontests/model_inheritance_regress/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,10 @@ class BusStation(Station):
163163

164164
class TrainStation(Station):
165165
zone = models.IntegerField()
166+
167+
class User(models.Model):
168+
username = models.CharField(max_length=30, unique=True)
169+
170+
class Profile(User):
171+
profile_id = models.AutoField(primary_key=True)
172+
extra = models.CharField(max_length=30, blank=True)

tests/regressiontests/model_inheritance_regress/tests.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66

77
import datetime
88
from operator import attrgetter
9+
from django import forms
910

1011
from django.test import TestCase
1112

1213
from .models import (Place, Restaurant, ItalianRestaurant, ParkingLot,
1314
ParkingLot2, ParkingLot3, Supplier, Wholesaler, Child, SelfRefParent,
1415
SelfRefChild, ArticleWithAuthor, M2MChild, QualityControl, DerivedM,
1516
Person, BirthdayParty, BachelorParty, MessyBachelorParty,
16-
InternalCertificationAudit, BusStation, TrainStation)
17+
InternalCertificationAudit, BusStation, TrainStation, User, Profile)
1718

1819

1920
class ModelInheritanceTest(TestCase):
@@ -408,3 +409,17 @@ def test_concrete_abstract_concrete_pk(self):
408409
)
409410
self.assertIs(BusStation._meta.pk.model, BusStation)
410411
self.assertIs(TrainStation._meta.pk.model, TrainStation)
412+
413+
def test_inherited_unique_field_with_form(self):
414+
"""
415+
Test that a model which has different primary key for the parent model
416+
passes unique field checking correctly. Refs #17615.
417+
"""
418+
class ProfileForm(forms.ModelForm):
419+
class Meta:
420+
model = Profile
421+
User.objects.create(username="user_only")
422+
p = Profile.objects.create(username="user_with_profile")
423+
form = ProfileForm({'username': "user_with_profile", 'extra': "hello"},
424+
instance=p)
425+
self.assertTrue(form.is_valid())

0 commit comments

Comments
 (0)