#21145 closed Uncategorized (fixed)
pk_trace fails with ValueError in case when one of the three interrelated models has different primary key type than the others
Reported by: | thepapermen | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.5 |
Severity: | Release blocker | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
In a project in which all of the models have UUIDs as the primary key, including the custom user model, this bug renders django.contrib.auth
permission checking unusable (because the Group and Permission models have integer primary keys, but the user has UUID one).
Permission.objects.filter(**{user_groups_query: user_obj})
in django.contrib.auth.backends.py
fails.
This bug also renders django guardian
3-rd party app unusable.
The root of the issue is that pk_trace
incorrectly retrieves the primary key type from intermediary model instead of the last model in the chain.
See line 212:
https://github.com/django/django/blob/d04e8f8c7869b79a6f848a94bd51ce71223c2df2/django/db/models/fields/related.py
Run check()
below to reproduce:
from django.db import models import string import random class ModelA(models.Model): pass class ModelB(models.Model): modela = models.ManyToManyField(ModelA, blank=True, null=True, ) class ModelC(models.Model): id = models.CharField(primary_key=True, max_length=1) # Or any non-integer PK field modelb = models.ManyToManyField(ModelB, blank=True, null=True, ) def check(): """ This function will fail with ValueError: invalid literal for int() with base 10: 'y' which, in turn, points us to the fact that pk_trace for pk of ModelC tries to operate with field type of ModelB instead. See line 212: https://github.com/django/django/blob/d04e8f8c7869b79a6f848a94bd51ce71223c2df2/django/db/models/fields/related.py """ a = ModelA.objects.create() b = ModelB.objects.create() b.modela.add(a) c = ModelC.objects.create(id=random.choice(string.ascii_letters)) c.modelb.add(b) return ModelA.objects.filter(modelb__modelc=c) # Will fail # But ModelA.objects.filter(modelb__modelc__pk=c.pk) works like a charm
Change History (3)
comment:1 by , 11 years ago
comment:2 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Hi,
The issue is not present on the master branch and from a quick git bisect
, it looks like it was fixed in commit 69597e5bcc89aadafd1b76abf7efab30ee0b8b1a.
Consequently, I'll mark this ticket as resolved
.
Thanks for the detailed report.
comment:3 by , 11 years ago
Wow, that's marvelous indeed! Than you for your efforts! That's a great reason to upgrade! )))
At least, I hope that the ticket will help some unfortunate soul that would stumble upon the issue while still using Django 1.5.
Good luck!
I'd also like to point that you need a relationship that spans at least three models. Two models are not enough to trigger the bug.