With the following models is it possible to get Category
objects and prefetch OrderLine
so that it can be accessed by category.orderlines.all()
?
class Category(models.Model):
name = models.CharField(...)
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products', ...)
name = models.CharField(...)
price = models.DecimalField(...)
class OrderLine(models.Model):
product = models.ForeignKey(Product, related_name='orderlines', ...)
I know you can do a nested prefetch through products but I'd like to access OrderLine
objects directly from a Category
rather than go through Product
from django.db.models import Prefetch
categories = Category.objects.prefetch_related(Prefetch(
'products__orderlines',
queryset=OrderLine.objects.filter(...)
))
for category in categories:
for product in category.products.all():
for line in product.orderlines.all():
...
Desired usage:
for category in categories:
for line in category.orderlines.all():
...
Update
Adding to_attr='orderlines'
results in:
ValueError: to_attr=orderlines conflicts with a field on the Product model.
Changing the attribute name to_attr='lines'
doesn't cause an error but the attribute isn't added to the Category
objects. It prefetches Product
then adds a lines
attribute to each product.
The closest I've come to this is using an ArraySubquery. The only downside being that lines
is a list of dictionaries rather than model instances.
Category.objects.annotate(
lines=ArraySubquery(
OrderLine.objects
.filter(category=OuterRef('id'))
.values(json=JSONObject(
id='id',
product_name='product__name',
quantity='quantity',
))
)
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With