I have 2 tables, Order and OrderDetails, on OrderDetails I have a field 'product_type'.
From the table Order I want to get all the product_type fields in a list.
Order.objects.filter(pk=1).annotate(type=F('product_type'))
I want the type
value to return a list of all product types, not just the first result like 'chair'.
Ex: type = ['chair', 'pencil']
Models:
class Order(models.Model):
user = models.ForeignKey(User, related_name="orders")
class OrderDetails(models.Model):
order = models.ForeignKey(Order, related_name="details")
quantity = models.SmallIntegerField(null=False, blank=False)
product_type = models.CharField(null=False, blank=False)
This is not something you can or should try to achieve with a queryset annotation. This is because annotations are only usable for aggregation functions like Count
, Sum
etc.
If I understood your question correctly, you can get this info when iterating over the queryset:
for order in Order.objects.all():
types = order.details.values_list('product_type', flat=True)
You can make this more efficient by prefetching the related OrderDetail
rows for each order:
for order in Order.objects.prefetch_related('details'):
types = order.details.values_list('product_type', flat=True)
Alternatively, you can retrieve some values from each order using this method:
queryset = Order.objects.values('id', 'user_id', 'details__product_type')
It should do a single db query. However, see the notes here about how this works: https://docs.djangoproject.com/en/1.9/ref/models/querysets/#values
Your queryset will output dicts instead of model instances. And you will not get a nice list of product_type
s... instead you will get repeated rows like:
[
{'id': 1, 'user_id': 1, 'product_type': 'chair'},
{'id': 1, 'user_id': 1, 'product_type': 'table'},
{'id': 2, 'user_id': 3, 'product_type': 'chair'},
...
]
...so you'll then have to group these rows in python into the data structure you want:
from collections import OrderedDict
grouped = OrderedDict()
for order in Order.objects.values('id', 'user_id', 'details__product_type'):
if order['id'] not in grouped:
grouped[order['id']] = {
'id': order['id'],
'user_id': order['user_id'],
'types': set(),
}
grouped[order['id']]['types'].add(order['details__product_type'])
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