Невозможно получить доступ к значениям словаря с помощью jinja
Вот мой views.py
def following(request):
currentUser = User.objects.get(pk=request.user.id)
currentUser_followings = Following_System.objects.get(user=currentUser).following
allPosts = Post.objects.all().order_by("-timestamp").reverse()
followingPosts = []
for user in currentUser_followings.all():
for post in allPosts:
if post.author == user:
followingPosts.append(post)
**post_likers_ids = {post.id: list(post.likers.values_list('id', flat=True)) for post in followingPosts}**
# Show 10 posts per page.
paginator = Paginator(followingPosts, 5)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, "network/following.html",{
"page_obj": page_obj,
"post_likers_ids" : post_likers_ids
})
Я отлаживаю, и post_likers_ids возвращаются: ({4: [2], 2: [1,3,5]}) И теперь в моем следующем html, почему условие if всегда ложно (Хотя оно должно быть истинным для некоторых, потому что я знаю ожидаемый входной вывод):
{% for post in page_obj %}
<div class="list-group-item">
{% with post_id=post.id %}
{% if user.id in post_likers_ids.post_id %}
<p>The user liked this </p>
{% else %}
<p>The user have not liked this </p>
{% endif %}
{% endwith %}
</div>
{% endfor %}
Вот моя модель, если это поможет:
class Post(models.Model):
content = models.TextField(blank=False)
author = models.ForeignKey("User", on_delete=models.CASCADE, related_name="author")
timestamp = models.DateTimeField(auto_now_add=True)
likers = models.ManyToManyField("User", related_name="liked_posts", blank=True)
def serialize(self):
likes_count = self.likers.count() #
likers = [user.id for user in self.likers.all()]
return {
"id": self.id,
"content": self.content,
"author": self.author.username,
"author_id": self.author.id,
"timestamp": self.timestamp.strftime("%b %d %Y, %I:%M %p"),
"likes": likes_count,
"likers" : likers,
}
Похоже, что при использовании шаблона jinja,
post_likers_ids.post_id
ведут себя странно, например, когда post_id = 4; используя
post_likers_ids.4
возвращает правильное значение, но использование post_likers_ids.post_id возвращает пустое значение
Вы можете проверить это с помощью:
{% if user.id in post_likers_ids[post_id] %}
<!-- … -->
{% endif %}
Но само построение такого словаря неэффективно, так как это вызовет n запросов для n постов.
Мы можем повысить эффективность, работая с JOIN для определения авторов, за которыми мы следим, и, кроме того, позволяя базе данных определить, понравился ли пост, с помощью подзапроса Exists
[Django-doc]:
from django.db.models import Exists, OuterRef
def following(request):
followingPosts = (
Post.objects.filter(author__following__user=request.user)
.order_by('-timestamp')
.annotate(
is_liked=Exists(
Post.likers.through.objects.filter(
user=request.user, post_id=OuterRef('pk')
)
)
)
.distinct()
)
# Show 10 posts per page.
paginator = Paginator(followingPosts, 5)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(
request,
'network/following.html',
{
'page_obj': page_obj,
},
)
Тогда в шаблоне мы получим:
{% for post in page_obj %}
<!-- … -->
{% if post.liked %}
<!-- … -->
{% endif %}
{% endfor %}
Я нашел ответ здесь, это обходной путь: Шаблон Django как искать значение словаря с помощью переменной