Shayestehhs
Shayestehhs

Reputation: 3

Get specific field of model in select_related

I have a query in my project:

qs = self.model.objects \
            .filter(user=self.request.user, pk__iexact=pk) \
            .select_related('shipping_addr', 'billing_addr', 'cart') \
            .first()

I want to optimize this query more than it is. I want to get only the 'id' and 'name' fields of shipping_addr. But this is not working:

qs = self.model.objects \
                .filter(user=self.request.user, pk__iexact=pk) \
                .select_related('shipping_addr', 'billing_addr', 'cart') \
                .only('shipping_addr__name','shipping_addr__id') \
                .first()

I know the reason that why this code is not running, I don't know what I have to do😕.

Upvotes: 0

Views: 2913

Answers (1)

Limecat
Limecat

Reputation: 411

select_related() is limited to single-valued relationships - foreign key and one-to-one. See: https://docs.djangoproject.com/en/3.1/ref/models/querysets/#select-related

So it needs to start in the model that has the foreign key and then you can select the related parent object to be fetched as well. So your self.model has a foreign key to shipping_addr.

You want to retrieve the shipping_addr.name by saving an extra database hit because

object=self.model.objects.get(pk=pk)
shipping_address_name=object.shipping_addr.name

hits your DB twice. So, instead, you do:

object=self.model.objects.select_related('shipping_addr').get(pk=pk)
shipping_address_name = object.shipping_addr.name

And that way you have eliminated one database hit, because your object will be fetched from the database already including the shipping_addr.

Unless your shipping_addr has lots of fields or are very expensive to retrieve, I wouldn't bother using only(), but if you insist you can add it. Without seeing your model it's hard to say.

Upvotes: 1

Related Questions