Opened 2 years ago

Closed 2 years ago

#34198 closed Bug (duplicate)

Django content type prefetching wrong data

Reported by: Mahavir Agrawal Owned by: Mahavir Agrawal
Component: Database layer (models, ORM) Version: 4.1
Severity: Normal 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

class Base1(models.Model): 
    value = models.CharField(max_length=20) 
 
 
class Base2(models.Model): 
    value = models.CharField(max_length=20) 
 
 
class LinkedWithBase1(models.Model): 
    f = models.ForeignKey(Foreign, on_delete=models.PROTECT, related_name="a_objects") 
 
 
class LinkedWithBase2(models.Model): 
    f = models.ForeignKey(OtherForeign, on_delete=models.PROTECT, related_name="b_objects") 
 
 
class Connection(models.Model): 
    ct = models.ForeignKey(ContentType, on_delete=models.PROTECT) 
    object_id = models.IntegerField() 
    object = GenericForeignKey(ct_field='ct', fk_field='object_id') 

The data presentation :-

1) Base1 Model

id value
1 Foreign

2) Base2 Model

id value
1 OtherForeign

3) LinkedWithBase1 model

id f_id (FK)
1 1

4) LinkedWithBase2 model

id f_id (FK)
1 1

Let's assume LinkedWithBase1 model content_type id is 1 and LinkedWithBase2 content_type id is 2.

Connection model

id ct_id object_id
1 1 1
2 2 1

1 row is connected with id 1 of LinkedWithBase1 model
2 row is connected with id 1 of LinkedWithBase2 model

When i was run below code

connections = Connection.objects.prefetch_related("object__f").all()

for i in connections:
    print(i.object.f.value)  

Actual Output
Foreign
Foreign

Expected Output
Foreign
OtherForeign

In 1st iteration i.object.f evaluate Base1 model instance which is right
In 2nd iteration i.object.f it should be take Base2 model instance but django takes as Base1 model instance
because of wrong prefetching occurs

But when i removed f from prefetch_related it gives me a expected result

Ex: connections = Connection.objects.prefetch_related("object").all()

i am very confident prefetching went wrong because i spent 5 hours to debug this issue in Django core and i got it doing wrong prefetching when it has a multiple content types as same name of key like f attribute in above code, I have patch for this.

I will very greatful if you give me a chance to fix this issue

Change History (2)

comment:1 by Mahavir Agrawal, 2 years ago

Owner: changed from nobody to Mahavir Agrawal
Status: newassigned

comment:2 by Mariusz Felisiak, 2 years ago

Has patch: unset
Resolution: duplicate
Status: assignedclosed

Duplicate of #34178 and #33651.

Note: See TracTickets for help on using tickets.
Back to Top