【问题标题】:Left Join in Django ORM在 Django ORM 中左连接
【发布时间】:2020-05-18 17:07:46
【问题描述】:

假设我有名为“Post”和“Reaction”的模型,我创建了一个 Post,保存了它,现在我想用一个 Reaction 对它做出反应。 现在,当我访问包含帖子列表的提要时,如果我有帖子,我想显示我的反应。

这意味着: {% if post.my_reaction %}{{ post.my_reaction.contents }}{% endif %} 现在,显然我想加载的不仅仅是一篇文章;没有我的反应的帖子。

我知道我曾经在 PHP 中使用 SQL 来解决这个问题

SELECT * FROM Post 
LEFT JOIN Reaction ON Reaction.Post = Post.id AND Reaction.Author = <me>

我的模型:

class Post(models.Model):
    content = RichTextField()
    author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    datetime = models.DateTimeField(auto_add_now=True)

class Reaction(models.Model):
    reaction = models.CharField(max_length=1)
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="reactions")
    author = models.ForeignKey(User, on_delete=models.CASCADE)

我不太清楚如何在 Django 中实现这一点

【问题讨论】:

  • 你能展示你的models.py吗?
  • 也许这就是你要找的东西 - stackoverflow.com/a/37688104/4996863
  • @Charnel 不,这不是我想要的。我正在明确搜索左连接,如果帖子上有我的反应,则查询中的该条目包含反应对象。
  • 好的,让我们再问一个问题 - 因为contentPost 模型上的一个字段,所以您唯一需要Reaction 的就是知道用户是否对帖子做出了反应?如果是,这似乎是一个简单的布尔标志,可以添加注释。
  • 用户每个帖子的反应可以超过 1 条吗?

标签: django orm left-join


【解决方案1】:

只需进入raw

results = Post.objects.raw("""
SELECT * FROM Post 
LEFT outer JOIN Reaction ON Reaction.Post = Post.id AND Reaction.Author = %s
""", [ '<me>', ])

【讨论】:

    【解决方案2】:

    您可以通过创建自定义模板标签来查询登录用户的帖子来实现此目的。尽管它是可选的,但对我来说,该查询的一个好地方应该是 Post 模型。

    class Post(models.Model):
        content = RichTextField()
        author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
        datetime = models.DateTimeField(auto_add_now=True)
    
       def user_reactions(self, user):
            return self.reactions.filter(author=user)
    

    然后,您需要创建一个自定义模板标签,以便在从请求中传入用户时,在 post 对象上调用该方法。

    from django import template
    
    register = template.Library()
    
    
    @register.simple_tag # (Django >= 1.9, earlier versions need to use `assignment_tag`)
    def post_user_reactions(post, user):
        return post.user_reactions(user)
    

    这将返回该用户的反应查询集,然后您可以在模板中对其进行迭代:

    {% post_user_reactions post user as user_reactions %}
    {% for reaction in user_reactions %}
      Do stuff with reaction object
    {% endfor %}
    

    请记住,在 for 循环中进行数据库查询(您可能会这样做,比如在这种情况下显示帖子列表),最终可能会非常昂贵。您需要添加 prefetch_related 或查询集注释来执行此操作。

    作为一些建议,Django ORM 在考虑数据库访问方面与传统 SQL 略有不同。考虑“左连接”无济于事——您需要考虑 Django 对象及其关系。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-08
      • 2015-10-15
      • 2022-01-05
      • 2021-12-03
      • 2017-11-27
      • 2021-08-28
      • 2018-10-10
      • 1970-01-01
      相关资源
      最近更新 更多