【问题标题】:How to make an Inner Join in django without foreign key?如何在没有外键的情况下在 django 中进行内部联接?
【发布时间】:2019-10-09 17:20:17
【问题描述】:

如何在 django 1.11 中声明 join on, 我想创建这个声明:

select t1.name ,t2.str, t2.num
from table_1 as t1
join table_2 as t2 on t2.product_id = t1.id and t2.section_num = 2;

the models:


class t1(UTModelTS):
    alt_keys = product_alt_keys
    name = utCharField()
    ...

class t2(UTModelTS):
    alt_keys= [('pr_id', 'section')]    
    str = utCharField()
    num = models.IntegerField()

    ...

我试过了

 t1 = t1.objects.filter(**params).exclude(**exclude)
 t1 = t1.select_related('t2')
`

但这没有任何意义,因为 acoridng 到 django doc : 选择相关 返回将“遵循”外键关系的 QuerySet... 来自https://docs.djangoproject.com/en/2.2/ref/models/querysets/

【问题讨论】:

  • 您能否在此处添加您的模型以便更好地理解。

标签: python sql django django-models


【解决方案1】:

您不应添加on 语句。 Django 的 ORM 会自动为你执行内连接。

想象一下这是我们的模型。 User 表和 Post 表。

class User(models.Model):
    name = models.CharField(max_length=30)
    surname = models.CharField(max_length=50)


class Post(models.Model):
    title = models.CharField(max_length=50)
    text = models.TextField()
    user = models.ForeignKey(to='User', on_delete=models.CASCADE) # this is FK field to users

用法

qs = Post.objects.select_related('user') # This will performs SQL INNER JOIN.
print(qs.query) # use query attribute to show what query is performed.

这将生成 SQL 查询

SELECT "myapp_post"."id", "myapp_post"."title", "myapp_post"."text", "myapp_post"."user_id", "myapp_user"."id", "myapp_user"."name", "myapp_user"."surname" FROM "myapp_post" INNER JOIN "myapp_user" ON ("myapp_post"."user_id" = "myapp_user"."id")

看看你的模型,,,

class t1(UTModelTS):
    alt_keys = product_alt_keys
    name = utCharField()
    t2 = models.ForeignKey(to='t2', on_delete=models.CASCADE)

class t2(UTModelTS):
    alt_keys= [('pr_id', 'section')]    
    str = utCharField()
    num = models.IntegerField()

将 t2 FK 添加到您的 t1 模型中。

查询

qs = t1.objects.select_related('t2')

qs = t1.objects.select_related('t2').filter(**lookup_kwargs).

select_related()返回QuerySet对象,你可以在select_related()之后使用QuerySet方法。

【讨论】:

  • 模型中的 ForeignKey() 字段在哪里?
  • t2 的字段不是 ForeignKeyto t1
  • 也许有 .extra ?
  • 你也可以使用 .extra(),因为 .extra() 也是 QuerySet 方法。但要执行连接 select_related()。
  • 我得到了异常值:无法将关键字“str”解析为字段。选择有:annotation、attribute1n、attribute1s、attribute2n、..al t1 的其余字段,当累了 qs = t1.objects.select_related('t2').filter(**lookup_kwargs)。
【解决方案2】:

不,遗憾的是没有有效/优雅的方式。

虽然您可以使用.raw()/RawSQL() 方法来解决这个问题。即使可以,它也可能比原始 SQL 慢很多。 https://docs.djangoproject.com/en/2.2/topics/db/sql/

【讨论】:

    猜你喜欢
    • 2018-05-05
    • 2017-10-27
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    相关资源
    最近更新 更多