I am having some difficulties to write this django queries. I have the following scenario.
I have three django models
For each interaction of a user and a visitor, I add some participants
participant_id entity_type entity_id
1 user 1
2 visitor 1
3 user 1
4 visitor 2
5 user 1
6 visitor 3
Entity type can be either user or visitor. How can I get related user and visitor data from entity id and entity type?
If you can refactor your solution to generic-relations, the answer is easy, because django already implements solution for you:
class Participant(Model):
entity_type = ForeignKey(ContentType)
entity_id = CharField(_('Sourced object id'))
content_object = GenericFields('entity_type', 'entity_id')
And after:
user_or_visitor = participant.content_object
more here: https://docs.djangoproject.com/en/5.0/ref/contrib/contenttypes/#generic-relations
Don't forget that you are getting here the “N+1 queries” performance problem "by default" and should take care of it with GenericPrefetch(). more here: https://docs.djangoproject.com/en/5.0/ref/contrib/contenttypes/#genericprefetch
If you can not change current project models:
Preparing data:
participants = Participant.objects.all()
visitors_ids = participants.objects.filter(entity_type="visitor").values_list('pk', flat=True)
users_ids = participants.objects.filter(entity_type="user").values_list('pk', flat=True)
users = User.objects.filter(id__in=users_ids).in_bulk()
visitors = Visitors.objects.filter(id__in=visitors_ids).in_bulk()
Here you have made only 2 database queries, but you have stored the objects in memory.
Somewhere later:
for participant in participants.objects.all():
participant.entity = None
if participant.entity_type == "visitor":
participant.entity = visitors[participant.entity_id]
elif participant.entity_type == "user":
participant.entity = users[participant.entity_id]
Here you have made only one request to db.
Of course, I can offer a more complex queryset request solution, but in my opinion, simple is better than complex.