Осталось присоединиться к Django ORM - PullRequest
1 голос
/ 03 февраля 2020

Скажем, у меня есть модели с именами "Пост" и "Реакция", и я создал пост, сохранил его, и теперь я хочу реагировать на него с помощью Реакции. Теперь, когда я захожу в свой канал, где находится список сообщений, я хочу показать свою реакцию, если бы у меня была одна.

Что означает: {% if post.my_reaction %}{{ post.my_reaction.contents }}{% endif %} Теперь, очевидно, я хочу загрузить больше, чем одну публикацию; посты, на которых нет моей реакции.

Я знаю, что раньше решал эту проблему с SQL в PHP с

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

Ответы [ 2 ]

1 голос
/ 03 февраля 2020

Просто загляните в raw:

results = Post.objects.raw("""
SELECT * FROM Post 
LEFT outer JOIN Reaction ON Reaction.Post = Post.id AND Reaction.Author = %s
""", [ '<me>', ])
1 голос
/ 03 февраля 2020

Этого можно добиться, создав собственный тег шаблона для запроса сообщений для вошедшего в систему пользователя. Хотя это и необязательно, для меня хорошим местом для этого запроса будет модель 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-l oop (как вы, вероятно, скажете, если в этом случае отображаете список сообщений) может оказаться очень дорогим. Для этого вам понадобится добавить prefetch_related или аннотацию набора запросов.

Как совет, Django ORM - это немного другой способ представления о доступе к базе данных, чем традиционный SQL. Думать о «левом соединении» не поможет - вам нужно думать о Django объектах и ​​их отношениях.

...