mirror of
https://github.com/django/django.git
synced 2025-06-02 10:09:12 +00:00
Fixed #36373 -- Fixed select_related() crash on foreign object for a composite pk.
Thanks Jacob Walls for the report and Sarah for the in-depth review.
This commit is contained in:
parent
42ab99309d
commit
8be0c0d690
@ -2678,7 +2678,11 @@ class RelatedPopulator:
|
||||
)
|
||||
|
||||
self.model_cls = klass_info["model"]
|
||||
self.pk_idx = self.init_list.index(self.model_cls._meta.pk.attname)
|
||||
# A primary key must have all of its constituents not-NULL as
|
||||
# NULL != NULL and thus NULL cannot be referenced through a foreign
|
||||
# relationship. Therefore checking for a single member of the primary
|
||||
# key is enough to determine if the referenced object exists or not.
|
||||
self.pk_idx = self.init_list.index(self.model_cls._meta.pk_fields[0].attname)
|
||||
self.related_populators = get_related_populators(klass_info, select, self.db)
|
||||
self.local_setter = klass_info["local_setter"]
|
||||
self.remote_setter = klass_info["remote_setter"]
|
||||
|
@ -9,4 +9,5 @@ Django 5.2.2 fixes several bugs in 5.2.1.
|
||||
Bugfixes
|
||||
========
|
||||
|
||||
* ...
|
||||
* Fixed a crash when using ``select_related`` against a ``ForeignObject``
|
||||
originating from a model with a ``CompositePrimaryKey`` (:ticket:`36373`).
|
||||
|
@ -14,17 +14,18 @@ class Token(models.Model):
|
||||
secret = models.CharField(max_length=10, default="", blank=True)
|
||||
|
||||
|
||||
class BaseModel(models.Model):
|
||||
class AbstractUser(models.Model):
|
||||
pk = models.CompositePrimaryKey("tenant_id", "id")
|
||||
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
|
||||
email = models.EmailField(unique=True)
|
||||
id = models.SmallIntegerField(unique=True)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class User(BaseModel):
|
||||
email = models.EmailField(unique=True)
|
||||
class User(AbstractUser):
|
||||
pass
|
||||
|
||||
|
||||
class Comment(models.Model):
|
||||
@ -35,13 +36,14 @@ class Comment(models.Model):
|
||||
related_name="comments",
|
||||
)
|
||||
id = models.SmallIntegerField(unique=True, db_column="comment_id")
|
||||
user_id = models.SmallIntegerField()
|
||||
user_id = models.SmallIntegerField(null=True)
|
||||
user = models.ForeignObject(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
from_fields=("tenant_id", "user_id"),
|
||||
to_fields=("tenant_id", "id"),
|
||||
related_name="comments",
|
||||
null=True,
|
||||
)
|
||||
text = models.TextField(default="", blank=True)
|
||||
integer = models.IntegerField(default=0)
|
||||
|
@ -184,6 +184,14 @@ class CompositePKTests(TestCase):
|
||||
with self.assertNumQueries(1):
|
||||
self.assertEqual(user.email, self.user.email)
|
||||
|
||||
def test_select_related(self):
|
||||
Comment.objects.create(tenant=self.tenant, id=2)
|
||||
with self.assertNumQueries(1):
|
||||
comments = list(Comment.objects.select_related("user").order_by("pk"))
|
||||
self.assertEqual(len(comments), 2)
|
||||
self.assertEqual(comments[0].user, self.user)
|
||||
self.assertIsNone(comments[1].user)
|
||||
|
||||
def test_model_forms(self):
|
||||
fields = ["tenant", "id", "user_id", "text", "integer"]
|
||||
self.assertEqual(list(CommentForm.base_fields), fields)
|
||||
|
Loading…
x
Reference in New Issue
Block a user