使用Django ORM中多对一表的值查询不同的模型实例

时间:2017-12-14 08:26:20

标签: python mysql django orm django-orm

我有三个模型,分别称为OrderAdjustmentLocation

我的Order模型(截断为仅显示相关字段)如下所示:

class Order(models.Model):
    id = models.CharField(max_length=48, primary_key=True)
    status = models.IntegerField(null=True, default=None)
    amount = models.FloatField(null=True, default=None)

虽然Adjustment模型如下所示:

class Adjustment(models.Model):
    id = models.CharField(max_length=48, primary_key=True)
    order = models.ForeignKey(Order, related_name='adjustments', null=True, default=None)
    type = models.CharField(max_length=50, null=True, default=None)
    amount = models.FloatField(null=True, default=None)
    location = models.ForeignKey(Location, null=True, blank=True, default=None)

最后Location模型如下所示:

class Location(models.Model):
    city = models.CharField(max_length=255, null=True, default=None)
    state = models.CharField(max_length=60, null=True, default=None)
    state_long = models.CharField(max_length=200, null=True, default=None)
    county = models.CharField(max_length=60, null=True, default=None)
    country = models.CharField(max_length=60, null=True, default=None)
    country_long = models.CharField(max_length=200, null=True, default=None)
    zipcode = models.CharField(max_length=32, null=True, default=None)
    longitude = models.FloatField(max_length=10, null=True, default=None)
    latitude = models.FloatField(max_length=10, null=True, default=None)
    timezone = models.CharField(max_length=60, null=True, default=None)

相关查询的代码位于:

orders = Order.objects.filter(
    adjustments__type='payment',
    adjustments__location__isnull=False,
    status__gte=200,
    status__lt=300

    ).exclude(
        adjustments__location__zipcode__in=['', '0000', '00000', 0000, 00000]
    ).values(
            # 'id',
            'adjustments__location__city',
            'adjustments__location__state',
            'adjustments__location__country'
    ).annotate(
        bookings=Count('amount'), #, distinct=True),
        total_booking_value=Sum('amount'),
        average_booking_value=Avg('amount')
    )

问题陈述:

获取城市,州和国家/地区匹配的所有不同订单,并计算订单数量(预订),价值和平均值。

目前,对于单个order,有时会对“付款”类型进行多次调整,因此会发生重复。如果我将id字段作为连接值添加,它只会给我一个订单及其location和收入统计信息。我可以迭代这些并进行自己的计算,同时忽略order.id的重复,但这似乎浪费了一个非常好的ORM查询。

注意:我在.distinct()命令后尝试.filter()但没有任何效果。

有趣的是,我试图在distinct=True命令中添加Count(),这减少了订单的数量......但这个数字没有意义并且是错误的(将数字从29减少到12,但正确的数字是28,因为有一个重复order)。

如果有人有任何建议,解决方案或我的代码存在任何基本问题,请告诉我们!我将非常感激!

1 个答案:

答案 0 :(得分:0)

所以你说:

  

获取城市,州和国家/地区匹配的所有不同订单,并计算订单数量(预订),价值和平均值。

我在您查找所有调整次数,每个城市的总数和平均值时,将其解释为您的查询示例。

我不确定您要添加的金额:订单金额或调整金额。由于我没有看到你如何汇总每个地点的订单金额 - 因为地点只与调整挂钩 - 我会假设你想要调整金额。

如果我的所有假设都是正确的,您应该通过位置模型。为简单起见,我省略了您的过滤器和排除项。

Location.objects.values(city)
  .annotate(
    bookings=Count('adjustments__amount'),  
    total_booking_value=Sum('adjustments__amount'), 
    average_booking_value=Avg('adjustments__amount')
  )

这应该给你这样的东西:

{'city': 'Dallas', 'bookings': 3, 'total_booking_value': 724.0, 'average_booking_value': 241.33333333333334}, 
{'city': 'Los Angeles', 'bookings': 2, 'total_booking_value': 434.0, 'average_booking_value': 217.0}, 
{'city': 'New York', 'bookings': 3, 'total_booking_value': 745.0, 'average_booking_value': 248.33333333333334}