Запрос Django для получения любимых сообщений пользователя?

#django #django-models #django-templates

#django #django-модели #django-шаблоны

Вопрос:

Меня немного смущает жаргон Django. Итак, у меня есть 3 модели: Post, UserProfile (пользователь), Избранное. Избранное отслеживает, какие сообщения пользователь выбрал в избранное.

Сообщение—> Избранное<— Пользователь / UserProfile

Любимая модель:

 class Favorite(models.Model):
    user = models.ForeignKey(User, unique=False)
    post = models.ForeignKey(Post, unique=False)

    def __unicode__(self):
        return self.user.username
  

Модель пользовательского профиля:

 class UserProfile(models.Model) :
    user = models.ForeignKey(User, unique=True)

    def get_favorites(self):
        if self.user:
            return self.user.favorite_set.all()
  

В моем представлении post_list я передаю все сообщения в свой шаблон, и в шаблоне у меня есть цикл for, который отображает все сообщения.

 {% for post in post_list %}
<hr/>
<div id=”post_{{ post.id }}”>
    {% include 'posts/_post.html' %}
</div>
{% endfor %}
  

Теперь в этом цикле for я хотел бы ввести логику, которая будет отображать «Избранное!», если вошедший в систему пользователь выбрал сообщение в избранном. Я думаю, что обычный SQL -это что-то вроде этого:

 SELECT favorite.post FROM favorite WHERE favorite.user = user.id
  

Так что в цикле шаблона я могу сделать

 {% if post in the.above.SQL.query%}Favorited!{% endif %}
  

По какой-то причине я просто не могу перевести это на Django lingo. Мы высоко ценим вашу помощь!

Ответ №1:

Следует признать, что ваша Favorite модель на самом деле является сквозной таблицей отношений «многие ко многим» между Post и User. Django действительно может управлять этим автоматически, если вы где-то объявите ManyToManyField . Лично я бы сделал это в UserProfile — так что связь фактически становится одной между Post и UserProfile:

 class UserProfile(models.Model):
    favorites = models.ManyToManyField(Post, related_name='favorited_by')
  

Теперь вам не нужен ваш get_favorites метод, поскольку он доступен через userprofile.favorites.all() . Вы могли просто использовать это как есть в шаблоне:

 {% if post in userprofile.favorites.all %}Favorited!{% endif %}
  

но в конечном итоге это будет крайне неэффективно, поскольку вы будете выполнять один и тот же идентичный запрос для каждого сообщения в вашем списке сообщений. Итак, используйте {% with %} тег, чтобы получить избранное один раз перед циклом:

 {% with userprofile.favorites.all as favorite_posts %}
  {% for post in post_list %}
    {% if post in favorite_posts %}Favorited{% endif %}
    ...
  {% endfor %}
{% endwith %}
  

Комментарии:

1. Сработало как волшебное заклинание. Я никогда не использовал ManyToMany, никогда не обращал на это особого внимания. Теперь я знаю! Спасибо!

Ответ №2:

Хотя Дэниел правильно подметил, я просто опубликую запрос, который вы хотели 🙂

 Post.objects.filter(favorite__user=user)
  

Комментарии:

1. Может кто-нибудь указать на документацию django для такого использования. Я думал, вы можете перемещаться только по таблицам, начиная с внешнего ключа tables?

Ответ №3:

Поскольку это отношения «многие ко многим», fav_post = user.favourite.all() вы можете передать это fav_post в context. Затем в шаблоне вам нужно будет повторить этот контекстный ключ