Django.urls.exceptions.NoReverseMatch: Не найден реверс для 'like_post' с аргументами '('',)'
Здесь полная ошибка: Reverse for 'like_post' с аргументами '('',)' не найден. Проверен 1 шаблон(ы): ['recipe/like/(?P[0-9]+)\Z']
Я подозреваю, что есть какая-то проблема с post_if
, но я не могу указать, что именно не так.
Я действительно не знаю, что делать, я думаю, что перепробовал все(.
views.py:
def LikeView(request, pk):
post = get_object_or_404(models.Recipe, id=request.POST.get('post_id'))
liked = False
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
liked = False
else:
post.likes.add(request.user)
liked = True
return HttpResponseRedirect(reverse('recipe-detail', args=[str(pk)]))
templates:
{% block content %}
<form action="{% url 'like_post' post.pk %}"
method = "POST">
{% csrf_token %}
<form action="{% url 'like_post' post.pk %}" method="POST">
{% csrf_token %}
{% if user.is_authenticated %}
{% if liked %}
<button type="submit", name="post_id", value="{{ post.id }}", class="btn btn-danger btn-sm">Unlike</button>
{% else %}
<button type="submit", name="post_id", value="{{ post.id }}", class="btn btn-primary btn-sm">Like</button>
{% endif %}
{% else %}
<small><a href="{% url 'login' %}">Login</a> to like</small>
{% endif %}
- {{ total_likes }} Likes
</form>
models.py:
class Recipe(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
ingredients = models.ManyToManyField(Ingredient)
likes = models.ManyToManyField(User, related_name='blog_posts')
def get_absolute_url(self):
return reverse("recipes-detail", kwargs={"pk": self.pk})
def total_likes(self):
return self.likes.count()
def __str__(self):
return self.title
Исходя из ошибки, очень вероятно, что в шаблоне нет переменной с именем post
. Скорее всего, это recipe
.
Но шаблон довольно странный: вы кодируете первичный ключ и в url, и в POST-параметрах, а кроме того, делаете две формы, одна из которых вложена в другую.
{% block content %}
<form action="{% url 'like_post' recipe.pk %}" method = "POST">
{% csrf_token %}
{% if user.is_authenticated %}
{% if liked %}
<button type="submit" class="btn btn-danger btn-sm">Unlike</button>
{% else %}
<button type="submit" class="btn btn-primary btn-sm">Like</button>
{% endif %}
{% else %}
<small><a href="{% url 'login' %}">Login</a> to like</small>
{% endif %}
- {{ total_likes }} Likes
</form>
Мы также можем немного увеличить вид с помощью:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
@login_required
def like(request, pk):
liked = False
removed, __ = models.Recipe.likes.through.filter(
recipe_id=pk, user_id=request.user.id
).delete()
if not removed:
models.Recipe.likes.through.create(recipe_id=pk, user_id=request.user.id)
return redirect('recipe-detail', pk)
Здесь нам не нужно сначала извлекать элемент Recipe
, а сразу же попытаться удалить записи, подобные recipe_id
и user_id
. Если запись не удаляется, мы продолжаем создавать ее.
Note: You can limit views to a view to authenticated users with the
@login_required
decorator [Django-doc].
Примечание: Функции обычно пишутся в snake_case, а не PascalCase, поэтому рекомендуется рекомендуется переименовать вашу функцию в
like
, а не в.LikeView
Note: You can make use of
redirect(…)
[Django-doc] instead of first callingreverse(…)
[Django] and then wrap it in aHttpResponseRedirect
object [Django-doc]. Theredirect(…)
function does not only offer a more convenient signature to do this, it also for example will use the.get_absolute_url()
method [Django-doc] if you pass it a model object.