Fixed #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
This commit is contained in:
Anssi Kääriäinen 2012-04-20 17:34:29 +00:00
parent 3d5d0be499
commit 53fb45c6d8
3 changed files with 30 additions and 4 deletions

View File

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

View File

@ -163,3 +163,10 @@ class BusStation(Station):
class TrainStation(Station): class TrainStation(Station):
zone = models.IntegerField() zone = models.IntegerField()
class User(models.Model):
username = models.CharField(max_length=30, unique=True)
class Profile(User):
profile_id = models.AutoField(primary_key=True)
extra = models.CharField(max_length=30, blank=True)

View File

@ -6,6 +6,7 @@ from __future__ import absolute_import
import datetime import datetime
from operator import attrgetter from operator import attrgetter
from django import forms
from django.test import TestCase from django.test import TestCase
@ -13,7 +14,7 @@ from .models import (Place, Restaurant, ItalianRestaurant, ParkingLot,
ParkingLot2, ParkingLot3, Supplier, Wholesaler, Child, SelfRefParent, ParkingLot2, ParkingLot3, Supplier, Wholesaler, Child, SelfRefParent,
SelfRefChild, ArticleWithAuthor, M2MChild, QualityControl, DerivedM, SelfRefChild, ArticleWithAuthor, M2MChild, QualityControl, DerivedM,
Person, BirthdayParty, BachelorParty, MessyBachelorParty, Person, BirthdayParty, BachelorParty, MessyBachelorParty,
InternalCertificationAudit, BusStation, TrainStation) InternalCertificationAudit, BusStation, TrainStation, User, Profile)
class ModelInheritanceTest(TestCase): class ModelInheritanceTest(TestCase):
@ -408,3 +409,17 @@ class ModelInheritanceTest(TestCase):
) )
self.assertIs(BusStation._meta.pk.model, BusStation) self.assertIs(BusStation._meta.pk.model, BusStation)
self.assertIs(TrainStation._meta.pk.model, TrainStation) self.assertIs(TrainStation._meta.pk.model, TrainStation)
def test_inherited_unique_field_with_form(self):
"""
Test that a model which has different primary key for the parent model
passes unique field checking correctly. Refs #17615.
"""
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
User.objects.create(username="user_only")
p = Profile.objects.create(username="user_with_profile")
form = ProfileForm({'username': "user_with_profile", 'extra': "hello"},
instance=p)
self.assertTrue(form.is_valid())