一对多关系中的Django查询

jal*_*nga 4 python mysql django

我有2个表Order和OrderDetails,在OrderDetails上我有一个字段“ product_type”。

我想从表Order中获取列表中的所有product_type字段。

Order.objects.filter(pk=1).annotate(type=F('product_type'))

我希望该type值返回所有产品类型的列表,而不仅仅是“椅子”之类的第一个结果。

例如: type = ['chair', 'pencil']

楷模:

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)
Run Code Online (Sandbox Code Playgroud)

Ane*_*pic 5

这不是您可以或应该尝试使用queryset批注实现的。这是因为,注释是仅可用于聚合函数喜欢CountSum

如果我正确理解了您的问题,则遍历queryset时可以获得以下信息:

for order in Order.objects.all():
    types = order.details.values_list('product_type', flat=True)
Run Code Online (Sandbox Code Playgroud)

您可以通过预取OrderDetail每个订单的相关行来提高效率:

for order in Order.objects.prefetch_related('details'):
    types = order.details.values_list('product_type', flat=True)
Run Code Online (Sandbox Code Playgroud)

另外,您可以使用此方法从每个订单中检索一些值:

queryset = Order.objects.values('id', 'user_id', 'details__product_type')
Run Code Online (Sandbox Code Playgroud)

它应该执行一个数据库查询。但是,请参阅此处的注释以了解其工作方式:https : //docs.djangoproject.com/en/1.9/ref/models/querysets/#values

您的查询集将输出字典而不是模型实例。而且您不会得到很好的product_types 列表...相反,您将得到重复的行,例如:

[
    {'id': 1, 'user_id': 1, 'product_type': 'chair'},
    {'id': 1, 'user_id': 1, 'product_type': 'table'},
    {'id': 2, 'user_id': 3, 'product_type': 'chair'},
    ...
]
Run Code Online (Sandbox Code Playgroud)

...因此您必须将python中的这些行分组为所需的数据结构:

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'])
Run Code Online (Sandbox Code Playgroud)