mirror of
https://github.com/django/django.git
synced 2025-06-04 02:59:13 +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.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.related_populators = get_related_populators(klass_info, select, self.db)
|
||||||
self.local_setter = klass_info["local_setter"]
|
self.local_setter = klass_info["local_setter"]
|
||||||
self.remote_setter = klass_info["remote_setter"]
|
self.remote_setter = klass_info["remote_setter"]
|
||||||
|
@ -9,4 +9,5 @@ Django 5.2.2 fixes several bugs in 5.2.1.
|
|||||||
Bugfixes
|
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)
|
secret = models.CharField(max_length=10, default="", blank=True)
|
||||||
|
|
||||||
|
|
||||||
class BaseModel(models.Model):
|
class AbstractUser(models.Model):
|
||||||
pk = models.CompositePrimaryKey("tenant_id", "id")
|
pk = models.CompositePrimaryKey("tenant_id", "id")
|
||||||
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
|
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
|
||||||
|
email = models.EmailField(unique=True)
|
||||||
id = models.SmallIntegerField(unique=True)
|
id = models.SmallIntegerField(unique=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
class User(BaseModel):
|
class User(AbstractUser):
|
||||||
email = models.EmailField(unique=True)
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Comment(models.Model):
|
class Comment(models.Model):
|
||||||
@ -35,13 +36,14 @@ class Comment(models.Model):
|
|||||||
related_name="comments",
|
related_name="comments",
|
||||||
)
|
)
|
||||||
id = models.SmallIntegerField(unique=True, db_column="comment_id")
|
id = models.SmallIntegerField(unique=True, db_column="comment_id")
|
||||||
user_id = models.SmallIntegerField()
|
user_id = models.SmallIntegerField(null=True)
|
||||||
user = models.ForeignObject(
|
user = models.ForeignObject(
|
||||||
User,
|
User,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
from_fields=("tenant_id", "user_id"),
|
from_fields=("tenant_id", "user_id"),
|
||||||
to_fields=("tenant_id", "id"),
|
to_fields=("tenant_id", "id"),
|
||||||
related_name="comments",
|
related_name="comments",
|
||||||
|
null=True,
|
||||||
)
|
)
|
||||||
text = models.TextField(default="", blank=True)
|
text = models.TextField(default="", blank=True)
|
||||||
integer = models.IntegerField(default=0)
|
integer = models.IntegerField(default=0)
|
||||||
|
@ -184,6 +184,14 @@ class CompositePKTests(TestCase):
|
|||||||
with self.assertNumQueries(1):
|
with self.assertNumQueries(1):
|
||||||
self.assertEqual(user.email, self.user.email)
|
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):
|
def test_model_forms(self):
|
||||||
fields = ["tenant", "id", "user_id", "text", "integer"]
|
fields = ["tenant", "id", "user_id", "text", "integer"]
|
||||||
self.assertEqual(list(CommentForm.base_fields), fields)
|
self.assertEqual(list(CommentForm.base_fields), fields)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user