J'ajoute une fonctionnalité similaire dans mon site Web où les utilisateurs peuvent aimer les messages des autres.
J'ai fait cela avec succès, mais j'ai un problème. Cela vérifie si l'utilisateur a déjà aimé le message, ce qui doit être effectué spécifiquement dans ma vue HOME.
C'est pour que je puisse rendre ma page d'accueil. Pour rencontrer ce problème, j'effectue un .annotate () sur mes messages lors de leur récupération, et je vois si un utilisateur a aimé un message.
Je le transmets ensuite à mon modèle d'accueil et vérifie si l'utilisateur existe dans la propriété posts likes.
Voici le code associé.
models.py:
{% if liked_or_not == True %} <a href="javascript:{document.getElementById('likepost{{ post.id }}').submit()}"><button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Unlike {{ post.total_likes }} </button></a> {% else %} <a href="javascript:{document.getElementById('likepost{{ post.id }}').submit()}"><button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Like {{ post.total_likes }} </button></a> {% endif %} <form id="likepost{{ post.id }}" method="POST" action="{% url 'likepost' post.id %}"> {% csrf_token%} <input type="hidden"> </form>
views.py:
def home(request): posts = Post.objects.all() liked_or_not = Post.objects.annotate(likes__user=request.user) return render(request, 'posts/home.html', {'posts': posts, 'liked_or_not': liked_or_not})
home.html:
class Post(models.Model): file = models.ImageField(upload_to='images/') summary = models.TextField(max_length=600) pub_date = models.DateTimeField(auto_now=True) user = models.ForeignKey(User, on_delete=models.CASCADE) likes = models.ManyToManyField(User, through='Like', related_name='likes') def __str__(self): return self.user.username def pub_date_pretty(self): return self.pub_date.strftime('%b %e %Y') def summary_pretty(self): return self.summary[:50] @property def total_likes(self): return self.likes.count() class Like(models.Model): status = models.BooleanField() post = models.ForeignKey(Post, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE)
3 Réponses :
Je ne comprends pas très bien ce que tu veux faire. Si vous voulez vérifier si l'utilisateur a aimé au moins un message, vous pouvez le faire comme ceci:
liked_or_not = Likes.objects.filter(post_id=post_id, user=request.user).exists()
Si vous souhaitez vérifier si un utilisateur a aimé un message spécifique, vous pouvez le mettre comme ceci:
liked_or_not = Like.objects.filter(user=request.user).exists
annoter a un but différent. Il annote chaque objet du QuerySet avec la liste d'expressions de requête fournie. Une expression peut être une valeur simple, une référence à un champ sur le modèle (ou tout autre modèle associé), ou une expression agrégée (moyennes, sommes, etc.) qui a été calculée sur les objets qui sont liés aux objets dans le QuerySet. en savoir plus ici https://docs.djangoproject.com/en/2.2/ref/models/querysets/#annotate
Pour ceux qui viennent ici pour d'autres possibilités de débogage du message d'erreur, j'avais fait une erreur et entré dans une requête analogue à
Like.objects.filter(user=request.user).values('status', flat=True) # instead of the correct Like.objects.filter(user=request.user).values_list('status', flat=True)
J'ai rencontré un problème similaire et résolu en utilisant .annotate
et ci-dessous est ma définition de Like dans models.py
filter_kwargs = {} filter_kwargs["writing"] = OuterRef("pk") filter_kwargs["user"] = request_user subquery = Like.objects.filter(**filter_kwargs) writing = ( Writing.objects.annotate(user_likes=Exists(subquery)) .get(id=id) )
dans views.py
class Like(models.Model): user = models.ForeignKey( "users.User", on_delete=models.CASCADE, related_name="likes" ) writing = models.ForeignKey( "writings.Writing", on_delete=models.CASCADE, related_name="likes" )