10

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

在下面的模型中,我想在 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:无法添加或更新子行:外键约束失败

4

3 回答 3

15

不,不幸的是,没有有效的方法。

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

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

于 2013-05-21T12:08:13.397 回答
11

DjangoForeignKey与 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`);" 

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

希望能帮助到你。

于 2019-05-24T09:16:30.350 回答
10

只是重新发布一些相关的答案,所以每个人都可以看到它。取自这里:比较两个列表中的元素时使用 django ORM 的最有效方法

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

我假设您的Model1Model2不相关,否则您将能够使用Django 的相关对象 接口。您可以采取以下两种方法:

  1. 使用extra和一个 SQL 子查询:

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

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

  2. 使用原始 SQL 查询

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

第二个问题:枚举结果

两种方法:

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

    enumerate(Model1.objects.all())
    
  2. 您可以使用此答案中描述的技术在 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 ...''')
    
于 2015-08-05T14:21:13.650 回答