Adrian
Adrian

Reputation: 198

Django complex query to parent

I am using django and I am having a little trouble figuring out how to handle complex queries to the database. I have two models:

Parent:

id = models.AutoField(primary_key = True)
name = models.CharField(max_length = 60)
category = models.ForeignKey(Categories, on_delete = models.CASCADE)

And son:

id = models.AutoField(primary_key = True)
name = models.CharField(max_length = 60)
parent = models.ForeignKey(Parent, on_delete = models.CASCADE)

Basically, I have an object with a queryset of sons, and I need to filter this queryset by certain categories of the parent. For example, filter all sons where parent category is 9, 10 or 11.

I know how to use Q to do the OR part, but I don't know how to filter by a field in the parent.

Upvotes: 2

Views: 3955

Answers (3)

yadavankit
yadavankit

Reputation: 353

You don't have to use Q for this type of query. I would actually recommend keeping this simple as said in the zen of Python.

If you want those Son objects which have their parents in categories 9, 10 and 11 (since you have a Categories model as well, I am gonna suppose Categories model has a field number having respective category numbers), perform this query :

sons = Son.objects.filter(parent__category__number__in=[9,10,11])

One caveat however is, if you have to get parent object of each Son object in sons Queryset (here, taking the first Son object), you have to do sons.first().parent which hits the database with one more query because Querysets are lazily evaluated.

To prevent this from happening, and fundamentally keeping database hits limited, do the below query (only if you are sure you'll need parent object of Sons) :

sons = Son.objects.filter(parent__category__number__in=[9,10,11]).select_related('parent')

This will pre-populate parent for each Son object in sons Queryset.

Also, Models are named singular, so I would recommend changing Categories to Category

Upvotes: 2

Lemayzeur
Lemayzeur

Reputation: 8525

Django offers a powerful and intuitive way to “follow” relationships in lookups.
Try this using Q from django.db.models
Official Django Documentation

Son.objects.filter(Q(parent__cateogory__id='') | Q(parent__cateogy__name=''))

Upvotes: 2

Chiefir
Chiefir

Reputation: 2671

Try something like that:

sons = Son.objects.filter(parent__category__in = [9, 10, 11]).select_related('parent')

You have to use __ (double underscores) to access a ForeignKey model's fields.

Upvotes: 7

Related Questions