Django 使用 ORM 和条件 Where 子句连接表

Posted

技术标签:

【中文标题】Django 使用 ORM 和条件 Where 子句连接表【英文标题】:Django join tables with ORM and conditional Where clause 【发布时间】:2019-03-15 16:07:04 【问题描述】:

我有 4 张桌子要加入;人员、机器和地点。如果请求正文包含过滤数据,我想加入这些表并将 where 子句添加到 ORM 查询的末尾。这是我的模型和原始查询(我想在 django ORM 中编写此查询)和 where 子句的 if 条件示例;

模型;

class Sales(models.Model):
    MachineId = models.ForeignKey(Machines,on_delete=models.CASCADE,db_column='MachineId',related_name='%(class)s_Machine')
    PersonnelId = models.ForeignKey(Personnels,on_delete=models.CASCADE,db_column='PersonnelId',related_name='%(class)s_Personnel')
    LocationId = models.ForeignKey(Locations,on_delete=models.CASCADE,db_column='LocationId',related_name='%(class)s_Location')
    class Meta:
        db_table = "Sales"

class Machines(models.Model):
    Name = models.CharField(max_length=200)
    Fee = models.DecimalField(max_digits=10,decimal_places=3)
    class Meta:
        db_table = "Machines"

class Personnels(models.Model):
    name = models.CharField(max_length=200)
    surname = models.CharField(max_length=200)
    class Meta:
        db_table = "Personnels"


class Locations(models.Model):
    Latitude = models.FloatField()
    Longitude = models.FloatField()
    LocationName = models.CharField(max_length=1000)
    class Meta:
        db_table = "Locations"

如您所见,我有 4 个模型。 “销售”表具有其他人的外键。我想使用这些外键获取表中的所有信息。(使用内连接)

    query = '''select * from "Sales" as "SL" INNER JOIN "Personnels" as "PL" ON ("SL"."PersonnelId" = "PL"."user_id") INNER JOIN "Machines" as "MC" ON ("SL"."MachineId" = "MC"."id")    INNER JOIN "Locations" as "LC" ON ("SL"."LocationId" = "LC"."id") '''
    if request.method=='POST':
        if request.data['personnel_name'] and request.data['personnel_name'] is not None:
            personnel_name = request.data['personnel_name']
            condition = '''WHERE "PL"."name" = '0' '''.format(personnel_name)
            query = query+condition

正如所见,有很多引号(如果我不写,postgresql 会麻烦)并且代码不干净。

我的问题是,如何使用 django ORM 编写此查询?如您所见,我想动态添加 where 条件。我怎样才能做到这一点?

【问题讨论】:

您应该在此处添加您的型号代码。一般模式是这样的。 Sales.objects.filter(personell__name=name)。 docs.djangoproject.com/en/2.1/topics/db/queries/… 仅从这段代码中,我并不清楚 Location、Personell、Machine 和 Sale 表之间的关系,以及输出中需要哪些字段。 你说得对,我添加了我的模型。 请尽可能用最简单的语言描述您想要完成的查询(例如“我希望所有位置都至少有一台机器”)等。这样会更容易提供帮助。 我写了一个简短的描述。 【参考方案1】:

我将使用传统的命名方式,只有类名大写,模型名单数。

class Sale(models.Model):
    machine = models.ForeignKey(Machine, on_delete=models.CASCADE)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    location = models.ForeignKey(Location, on_delete=models.CASCADE)

db_columndb_table 如果您必须使用现有数据库连接 django 应用程序,则很有用。如果没有,django 将默认创建合理的表名。表名可以与模型字段名不同。

要创建join where,请使用queryset filter。

Sale.objects.filter(person__name='Jane Janes')

您可能不需要更多的连接,因为 django 会在需要时执行额外的查询,但可以使用 select_related 来实现,并且可以为您提供更好的性能,因为它减少了所需的 sql 查询总数。

Sale.objects.filter(person__name='Jane Janes').select_related('machine', 'person', 'location')

在评估查询集时检查将执行的实际 SQL 会很有用。您可以通过访问QuerySet.query 属性来做到这一点。

queryset = Sale.objects.select_related('machine').filter(
    person__name='Jim', location__name='London')

print(queryset.query)

【讨论】:

以上是关于Django 使用 ORM 和条件 Where 子句连接表的主要内容,如果未能解决你的问题,请参考以下文章

如何在 pynamodb ORM 中使用多个 where 条件

laravel orm where 条件中 mysql函数 怎么用

Django ORM 替换额外的 where

laravel orm where 条件中 mysql函数 怎么用

丰富 Eloquent ORM 的 where 查询条件的解析场景

在 Django 的 ORM 中使用带有 UPDATE 的子查询