在Django中是否有办法使用ORM编写查询,而不是原始SQL允许您在没有外键的情况下在另一个表上加入?通过查看文档,为了使One to One关系起作用,必须有一个外键存在?
在下面的模型中,我想在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:无法添加或更新子行:外键约束失败
答案 0 :(得分:11)
不,不幸的是,没有一种有效的方法。
.raw()
就是这样。即使它可能会比原始SQL慢很多。
有一篇博客文章here详细说明如何使用query.join()
,但正如他们自己所指出的那样。这不是最好的做法。
答案 1 :(得分:7)
只需重新发布一些相关答案,这样每个人都可以看到它。 取自这里:Most efficient way to use the django ORM when comparing elements from two lists
第一个问题:加入不相关的模型
我假设您的
Model1
和Model2
无关, 否则你就可以使用Django's related objects了 接口。您可以采取以下两种方法:
使用
extra
和SQL子查询:Model1.objects.extra(where = ['field in (SELECT field from myapp_model2 WHERE ...)'])
在某些数据库中,子查询的处理效率不高 (特别是MySQL)所以这可能不如下面的#2那么好。
- 醇>
Model1.objects.raw('''SELECT * from myapp_model1 INNER JOIN myapp_model2 ON myapp_model1.field = myapp_model2.field AND ...''')
第二个问题:枚举结果
两种方法:
您可以使用内置的
enumerate
函数枚举Python中的查询集:enumerate(Model1.objects.all())
- 醇>
您可以使用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 ...''')
答案 2 :(得分:0)
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
是必需的,如果没有ALTER TABLE `user_activity` ADD CONSTRAINT `xxx` FOREIGN KEY (`request_url`) REFERENCES `user_activity_link` (`url_description`);"
,Django将会构建如下的SQL:
$a = 1 ;DO { 'Starting Loop' ; $vischk = get-process | where-object {$_.mainwindowhandle -ne 0 -and $_.MainWindowTitle -eq 'Start - Microsoft Edge'} | select-object name, mainwindowtitle ; if (!($vischk)) {Write-Warning 'Microsoft Edge is off'}else{Write-Warning 'Closing Chrome' Stop-Process -name chrome} ; Write-Warning 'Active surveillance' ; Start-Sleep -s 15} While ($a -le 2)
我遇到了同样的问题,经过大量研究,我发现了上述方法。
希望有帮助。