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 calling reverse(…) [Django] and then wrap it in a HttpResponseRedirect object [Django-doc]. The redirect(…) 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.

Вернуться на верх