如何在Django中使用ORM实现指定的左连接SQL查询?
用Django ORM实现左连接查询
嘿,我来帮你搞定这个问题!首先得先明确你的Django模型结构,假设你的模型大概是这样的(如果和你的实际情况有出入,调整一下关联字段就行):
from django.db import models from django.contrib.auth.models import User class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() # 其他文章相关字段 class Upvote(models.Model): article = models.ForeignKey( Article, on_delete=models.CASCADE, related_name='upvotes' # 这个反向关联名很重要,用来从Article关联到Upvote ) user = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True)
接下来分两种场景给你解决方案:
场景1:获取文章对象及对应的所有点赞记录(面向对象的方式)
这是Django ORM最常用的方式,用prefetch_related来实现反向关联的左连接效果(底层会先查询所有文章,再批量查询对应的点赞记录,然后在Python层面关联,性能也很好):
# 获取所有文章,同时预加载对应的点赞记录 articles = Article.objects.all().prefetch_related('upvotes') # 遍历使用 for article in articles: print(f"文章标题: {article.title}") # 获取这篇文章的所有点赞记录 for upvote in article.upvotes.all(): print(f"点赞用户: {upvote.user.username}, 点赞时间: {upvote.created_at}") # 如果没有点赞记录,article.upvotes.all()会返回空QuerySet
场景2:生成和你SQL完全一致的单条左连接查询(返回扁平结果)
如果你需要的是和原生SQL一样的扁平结果集(每条记录包含文章字段+点赞字段,无点赞则点赞字段为NULL),可以用raw()方法直接执行你的SQL:
# 执行原生SQL查询 results = Article.objects.raw(""" select * from article_article left join article_upvote ON article_article.id=article_upvote.article_id """) # 遍历结果 for row in results: # 访问文章字段,比如row.title, row.content # 访问点赞字段,比如row.user_id, row.created_at(如果没有点赞,这些字段会是None) print(f"文章标题: {row.title}, 点赞用户ID: {row.user_id}")
另外补充一点:如果你不想用原生SQL,也可以用annotate结合Subquery来获取特定的点赞字段,但如果要获取所有点赞字段,原生SQL会更直接。
内容的提问来源于stack exchange,提问作者Kritika Shrivastava
相关产品推荐
相关产品推荐

