【问题标题】:Django JOIN query without foreign key没有外键的 Django JOIN 查询
【发布时间】:2013-05-16 04:27:40
【问题描述】:

在 Django 中有没有一种方法可以使用 ORM 编写查询,而不是原始 SQL,它允许您在没有外键的情况下在另一个表上 JOIN?查看文档,为了使一对一关系起作用,必须存在外键吗?

在下面的模型中,我想在 UserActivity.request_url 上运行一个 JOIN 查询到 UserActivityLink.url。

class UserActivity(models.Model):
    id = models.IntegerField(primary_key=True)
    last_activity_ip = models.CharField(max_length=45L, blank=True)
    last_activity_browser = models.CharField(max_length=255L, blank=True)
    last_activity_date = models.DateTimeField(auto_now_add=True)
    request_url = models.CharField(max_length=255L, blank=True)
    session_id = models.CharField(max_length=255L)
    users_id = models.IntegerField()
    class Meta:
        db_table = 'user_activity'

class UserActivityLink(models.Model):
    id = models.IntegerField(primary_key=True)
    url = models.CharField(max_length=255L, blank=True)
    url_description = models.CharField(max_length=255L, blank=True)
    type = models.CharField(max_length=45L, blank=True)
    class Meta:
        db_table = 'user_activity_link'

链接表对系统中的给定 URL 进行了更具描述性的翻译,这是系统将生成的某些报告所必需的。

我尝试创建从 UserActivity.request_url 到 UserActivityLink.url 的外键,但失败并出现以下错误:错误 1452:无法添加或更新子行:外键约束失败

【问题讨论】:

  • 我想知道如果您将 UserActivity.request_url 字段定义为使用 to_field='url' 的 ForeignKey 会发生什么。
  • 我通过 Workbench 尝试了同样的事情,但如果出现错误。我尝试创建从 UserActivity.request_url 到 UserActivityLink.url 的外键关系,但出现以下错误,不确定原因或真正含义:错误 1452:无法添加或更新子行:外键约束失败

标签: django django-models django-queryset


【解决方案1】:

不,遗憾的是没有有效的方法。

.raw() 就是为了这个确切的东西。即使可以,它也可能比原始 SQL 慢很多。

有一篇博文 here 详细说明了如何使用 query.join() 进行操作,但正如他们自己指出的那样。这不是最佳做法。

【讨论】:

    【解决方案2】:

    Django ForeignKey 与 SQL ForeignKey 不同。 Django ForeignKey 只是表示一个关系,它可以指定是否使用数据库约束。

    试试这个:

    request_url = models.ForeignKey(UserActivityLink, to_field='url_description', null=True, on_delete=models.SET_NULL, db_constraint=False)
    

    请注意,db_constraint=False必需的,没有它,Django 将构建如下 SQL:

    ALTER TABLE `user_activity` ADD CONSTRAINT `xxx` FOREIGN KEY (`request_url`) REFERENCES `user_activity_link` (`url_description`);" 
    

    我遇到了同样的问题,经过大量研究,我找到了上述方法。

    希望对你有帮助。

    【讨论】:

      【解决方案3】:

      只是转贴一些相关的答案,让大家看看。 取自这里:Most efficient way to use the django ORM when comparing elements from two lists

      第一个问题:加入不相关的模型

      我假设您的 Model1Model2 不相关, 否则你可以使用Django's related objects 界面。您可以采取以下两种方法:

      1. 使用 extra 和 SQL 子查询:

        Model1.objects.extra(where = ['field in (SELECT field from myapp_model2 WHERE ...)'])
        

        在某些数据库中子查询的处理效率不高 (尤其是 MySQL)所以这可能不如下面的 #2。

      2. 使用raw SQL query

        Model1.objects.raw('''SELECT * from myapp_model1
                           INNER JOIN myapp_model2
                           ON myapp_model1.field = myapp_model2.field
                           AND ...''')
        

      第二个问题:枚举结果

      两种方法:

      1. 您可以在 Python 中使用内置的enumerate 函数枚举查询集:

        enumerate(Model1.objects.all())
        
      2. 您可以使用this answer 中描述的技术在 MySQL 中进行枚举。像这样的:

        Model1.objects.raw('''SELECT *, @row := @row + 1 AS row
                           FROM myapp_model1
                           JOIN (SELECT @row := 0) rowtable
                           INNER JOIN myapp_model2
                           ON myapp_model1.field = myapp_model2.field
                           AND ...''')
        

      【讨论】:

        猜你喜欢
        • 2018-10-21
        • 2011-12-28
        • 2018-09-01
        • 2016-01-14
        • 1970-01-01
        • 1970-01-01
        • 2011-02-01
        • 2018-09-01
        • 2019-08-17
        相关资源
        最近更新 更多