#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. Затем в шаблоне вам нужно будет повторить этот контекстный ключ