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 子句连接表的主要内容,如果未能解决你的问题,请参考以下文章