Opened 7 hours ago
Last modified 105 minutes ago
#36704 assigned Bug
Proxy model with a CompositePrimaryKey fails system check with false positive: (models.E042) '<field>' cannot be included in the composite primary key
| Reported by: | Hal Blackburn | Owned by: | Hal Blackburn |
|---|---|---|---|
| Component: | Core (System checks) | Version: | 5.2 |
| Severity: | Release blocker | Keywords: | compositeprimarykey |
| Cc: | Hal Blackburn | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
A proxy subclass model of a parent model that uses CompositePrimaryKey causes manage.py check to fail:
$ python manage.py check
SystemCheckError: System check identified some issues:
ERRORS:
example.ProxyOrderLineItem: (models.E042) 'order_id' cannot be included in the composite primary key.
HINT: 'order_id' field is not a local field.
example.ProxyOrderLineItem: (models.E042) 'product_id' cannot be included in the composite primary key.
HINT: 'product_id' field is not a local field.
System check identified 2 issues (0 silenced).
This models.py module will reproduce the issue:
# Example from https://docs.djangoproject.com/en/5.2/topics/composite-primary-key/
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
class Order(models.Model):
reference = models.CharField(max_length=20, primary_key=True)
class OrderLineItem(models.Model):
pk = models.CompositePrimaryKey("product_id", "order_id")
product = models.ForeignKey(Product, on_delete=models.CASCADE)
order = models.ForeignKey(Order, on_delete=models.CASCADE)
quantity = models.IntegerField()
# This proxy model triggers the check error
class ProxyOrderLineItem(OrderLineItem):
class Meta:
proxy = True
The issue is caused by these two lines of the checks for classes with CompositePrimaryKey:
elif field not in meta.local_fields:
hint = f"{field_name!r} field is not a local field."
The meta.local_fields is empty for proxy subclasses, but the check passes for the parent class because the meta.local_fields contains the fields in the parent.
I believe this is a false-positive, as the proxy model seems to work as expected if the failed checks are suppressed.
Change History (4)
comment:1 by , 6 hours ago
| Has patch: | unset |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
comment:2 by , 4 hours ago
You're welcome! Sure, I'd be happy to make a patch.
Good idea to skip these checks for proxy models. Shall we return early from _check_composite_pk() at this point that if not isinstance(pk, CompositePrimaryKey): also returns early?
comment:3 by , 4 hours ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:4 by , 105 minutes ago
| Keywords: | compositeprimarykey added |
|---|---|
| Severity: | Normal → Release blocker |
Thanks for the report!
Would you like to prepare a patch?
Since
_check_composite_pk()has no proxy-model specific checks, we may also choose to skip the checks for proxy models. This would fix this issue and prevent duplicate errors reports when there are errors.