diff --git a/django/db/models/base.py b/django/db/models/base.py index fc38224345..e28add30a9 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -718,9 +718,13 @@ class Model(object): # Exclude the current object from the query if we are editing an # instance (as opposed to creating a new one) - if not self._state.adding and self.pk is not None: - qs = qs.exclude(pk=self.pk) - + # Note that we need to use the pk as defined by model_class, not + # 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 len(unique_check) == 1: key = unique_check[0] diff --git a/tests/regressiontests/model_inheritance_regress/models.py b/tests/regressiontests/model_inheritance_regress/models.py index bb5d77c51f..161569bcb3 100644 --- a/tests/regressiontests/model_inheritance_regress/models.py +++ b/tests/regressiontests/model_inheritance_regress/models.py @@ -163,3 +163,10 @@ class BusStation(Station): class TrainStation(Station): 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) diff --git a/tests/regressiontests/model_inheritance_regress/tests.py b/tests/regressiontests/model_inheritance_regress/tests.py index 8e2c56bd55..3cb6f9d603 100644 --- a/tests/regressiontests/model_inheritance_regress/tests.py +++ b/tests/regressiontests/model_inheritance_regress/tests.py @@ -6,6 +6,7 @@ from __future__ import absolute_import import datetime from operator import attrgetter +from django import forms from django.test import TestCase @@ -13,7 +14,7 @@ from .models import (Place, Restaurant, ItalianRestaurant, ParkingLot, ParkingLot2, ParkingLot3, Supplier, Wholesaler, Child, SelfRefParent, SelfRefChild, ArticleWithAuthor, M2MChild, QualityControl, DerivedM, Person, BirthdayParty, BachelorParty, MessyBachelorParty, - InternalCertificationAudit, BusStation, TrainStation) + InternalCertificationAudit, BusStation, TrainStation, User, Profile) class ModelInheritanceTest(TestCase): @@ -408,3 +409,17 @@ class ModelInheritanceTest(TestCase): ) self.assertIs(BusStation._meta.pk.model, BusStation) 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())