没有外键的 Django-queryset 连接

问题描述 投票:0回答:5

模型.py

class Tdzien(models.Model):
  dziens = models.SmallIntegerField(primary_key=True, db_column='DZIENS')
  dzienrok = models.SmallIntegerField(unique=True, db_column='ROK')


class Tnogahist(models.Model):
  id_noga = models.ForeignKey(Tenerg, primary_key=True, db_column='ID_ENERG')
  dziens = models.SmallIntegerField(db_column='DZIENS')

我想要的是得到 id_noga 其中 dzienrok=1234。我知道 dziens 应该是

dziens = models.ForeignKey(Tdzien)

但事实并非如此,我无法改变这一点。通常我会使用类似的东西

Tnogahist.objects.filter(dziens__dzienrok=1234)

但我不知道如何在没有外键的情况下连接和过滤这些表。

python django django-queryset
5个回答
24
投票

据我所知,没有外键就没有连接,但您可以使用两个查询:

Tnogahist.objects.filter(dziens__in=Tdzien.objects.filter(dzienrok=1234))


22
投票

可以通过执行原始 SQL 查询来连接两个表。但对于这种情况,它是相当令人讨厌的,所以我建议你重写你的 models.py。

您可以在此处查看如何执行此操作

它会是这样的:

from django.db import connection

def my_custom_sql(self):
    cursor = connection.cursor()    
    cursor.execute("select id_noga
                    from myapp_Tnogahist a
                    inner join myapp_Tdzien b on a.dziens=b.dziens
                    where b.dzienrok = 1234")
    row = cursor.fetchone()
    return row

7
投票

你能用

.extra
来做这个吗?来自https://docs.djangoproject.com/en/dev/ref/models/querysets/#extra

哪里/桌子

您可以定义显式 SQL WHERE 子句 — 也许是为了执行 非显式连接——通过使用 where。您可以手动添加表 使用表的 SQL FROM 子句。


7
投票

为@paul-tomblin 的答案提供更多背景信息,

值得一提的是 对于绝大多数 django 用户来说;最好的做法是实施传统的外键。 Django 强烈建议避免使用

extra()
表示“将此方法作为最后的手段”。然而,
extra()
仍然优于使用Manager.raw()的原始查询或使用django.db.connection

直接执行自定义SQL

这是一个如何使用 django 的 .extra() 方法实现此目的的示例:

Tnogahist.objects.extra(
    tables = ['myapp_tdzien'],
    where = [
        'myapp_tnogahist.dziens=myapp_tdzien.dziens',
        'myapp_tdzien.dzienrok=%s',
        ],
    params = [1234],
    )

与其他方法相比,使用

extra()
的主要吸引力在于它可以与 django 的查询集堆栈的其余部分(例如过滤器、排除、延迟、值和切片)很好地配合。所以你可以将它与传统的 django 查询逻辑一起插入。例如:
Tnogahist.objects.filter(...).extra(...).values('id_noga')[:10]


1
投票

如果选择两个模型的某些字段没有外键,可以使用以下方法。

#import
from django.db.models import Subquery, OuterRef
from django.db.models.expressions import RawSQL

#result
dziens_result = Tdzien.objects.filter(dzienrok=1234).annotate(
                tno_dziens=Subquery(Tnogahist.objects.filter(dziens=OuterRef('dziens')).values('dziens')
                        )
                ).values_list('dziens', 'tno_dziens', 'dzienrok','id_noga')
© www.soinside.com 2019 - 2024. All rights reserved.