【问题标题】:Django Queryset order by a not directly related model's fieldDjango Queryset 按不直接相关的模型字段排序
【发布时间】:2019-10-18 18:23:16
【问题描述】:

我有以下模型设计:

class Boat(models.Model):    
    name = models.CharField(max_length=30, null=False)
    harbour = models.ForeignKey(Harbour, null=True, on_delete=models.SET_NULL)

class Harbour(models.Model):
    name = models.CharField(max_length=60)
    city = models.ForeignKey(City, null=True, related_name='city_harbours',  on_delete=models.SET_NULL)

class City(models.Model):
    name = models.CharField(max_length=80)
    county = models.CharField(max_length=30, null=True)


class NearestCity(models.Model):
    city = models.ForeignKey(City, related_name='city', null=False, on_delete=models.CASCADE)
    near_city = models.ForeignKey(City, related_name='near_city', null=False, on_delete=models.CASCADE)
    weight = models.DecimalField(null=False, max_digits=25, decimal_places=20)

简要说明:

  • Boat 属于HarbourHarbour 属于City

  • 并非所有城市都有港口相关的。

  • NearestCity 是一个表格,其中存储了一个城市与其他城市的距离:weight 是一个十进制值,表示 city 与 _near_city_ 的距离。 “权重”值越小,城市与 near_city 越接近。例如:

city     near_city      weight
----    ---------       ------
London   Rome           2.210103
London   Manchester     0.113134

这意味着曼彻斯特比罗马更靠近伦敦。

要解决的问题:

给定一个没有任何港口相关的城市的名称,例如柏林,想要归还那些至少有一个港口相关的最近城市的所有船只。这艘船的查询集必须由weight DESC 订购。

我真的是 django 查询集的新手,我尝试使用 annotatesubqueriesaggregations 等来解决。但我无法实现。

【问题讨论】:

    标签: python django


    【解决方案1】:

    我会尝试raw sql。像这样的东西应该可以工作:

    city = selected_city_pk
    sql = """
        SELECT b.name, nc.weight, nc.near_city_id
        FROM appname_nearestcity nc
        JOIN appname_city c ON near_city_id = c.id
        JOIN appname_harbour h ON near_city_id = h.city_id
        JOIN appname_boat b ON h.id = b.harbour_id
        WHERE nc.city_id = %s
        ORDER BY nc.weight, b.name
    """
    results = Boat.objects.raw(sql, [city,])
    
    for r in results: print(r.id, r.name, r.weight, r.near_city_id)
    # boat_id, boat_name, weight, near_city_id
    >> 14 b-0-h-sochi-0 10 6
    >> 15 b-0-h-sochi-1 10 6
    >> 16 b-0-h-sochi-2 10 6
    >> 17 b-1-h-sochi-2 10 6
    >> 18 b-2-h-sochi-2 10 6
    >> 11 b-0-h-rome-0 55 5
    >> 12 b-1-h-rome-0 55 5
    >> 13 b-2-h-rome-0 55 5
    >> 4 b-0-h-brasilia-0 56 4
    >> 7 b-0-h-brasilia-1 56 4
    >> 10 b-0-h-brasilia-2 56 4
    >> 5 b-1-h-brasilia-0 56 4
    >> 8 b-1-h-brasilia-1 56 4
    >> 6 b-2-h-brasilia-0 56 4
    >> 9 b-2-h-brasilia-1 56 4
    >> 1 b-0-h-beijin-0 93 2
    >> 3 b-0-h-beijin-1 93 2
    >> 2 b-1-h-beijin-0 93 2
    

    请记住将表名替换为数据库中的实际表名,因为 Django 会为其添加应用程序名称前缀。

    【讨论】:

    • 非常感谢您的回答。此查询集返回 NearestCities.. 但我需要按重量排序的船。因为在那之后我需要对 Boat 对象应用另一个过滤器
    • 您阅读了链接吗?此查询集返回手动选择的字段和可能与某个模型不密切相关的项目。如果需要过滤,也可以在原始sql中进行。
    • 使用模型创建的数据库中的实际(默认)表名编辑了答案。
    • 太棒了,它运行完美..非常感谢您的帮助@Alex K.
    猜你喜欢
    • 2015-02-18
    • 1970-01-01
    • 2011-05-09
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 2022-06-17
    • 2015-10-26
    相关资源
    最近更新 更多