Python/Django маршрутизация путается при нажатии на кнопку
Я работаю над базовым учебником по django и застрял. Когда нажимается кнопка "избранное", я пытаюсь перенаправить пользователя на страницу reviews/favorite, которая затем перенаправит его на reviews/review_id, с которой он и начал. Вместо этого, всякий раз, когда я нажимаю кнопку избранного на странице, она перенаправляет меня на reviews/reviews/review_id, что не удается.
Интересно, что если я удалю часть /reviews/ из действия формы в файле single-review.html, то он направляет меня на /favorite, что не удается, потому что он не существует, но когда я возвращаю его обратно к reviews/favorite, я возвращаюсь к reviews/reviews/favorite в качестве маршрутизации. Кто-нибудь знает, что я делаю неправильно?
Views.py
from django.http.response import HttpResponse
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django import forms
from django.views import View
from django.views.generic.base import TemplateView
from django.views.generic import ListView
from django.views.generic.detail import DetailView
from django.views.generic.edit import FormView, CreateView
from .forms import ReviewForm
from .models import Review
# Create your views here.
# uses createview to handle all the data processing and then save data to database. Removes need for class ReviewForm in forms.py unless you want to customize
class ReviewView(CreateView):
model = Review
form_class = ReviewForm
template_name = "reviews/review.html"
success_url = "/thank-you"
class ThankYouView(TemplateView):
template_name = "reviews/thank_you.html"
# method allows you to set items to the context dictionary and them import that data into the thank-you.html file via the message variable
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["message"] = "This Works!"
return context
class ReviewsListView(ListView):
template_name = "reviews/review-list.html"
model = Review # do not instantiate when pointing to model
context_object_name = "reviews"
class SingleReviewView(DetailView):
template_name = "reviews/single-review.html"
model = Review
class AddFavoriteView(View):
def post(self, request):
print(request)
review_id = request.POST["review_id"]
request.session["favorite_review"] = review_id
return HttpResponseRedirect("reviews/" + review_id)
Models.py
from django.db import models
# Create your models here.
class Review(models.Model):
user_name=models.CharField(max_length=100)
review_text=models.TextField()
rating = models.IntegerField()
Forms.py
from .models import Review
class ReviewForm(forms.ModelForm):
class Meta:
model = Review
fields = "__all__"
labels = {
"user_name": "Your Name",
"review_text": "Your Feedback",
"rating": "Your Rating"
}
error_messages = {
"user_name": {
"required": "Your name must not be empty!",
"max_length": "Please enter a shorter name!"
}
}
Urls.py in /reviews
from django.urls import path
from . import views
urlpatterns = [
path("", views.ReviewView.as_view()),
path("thank-you", views.ThankYouView.as_view()),
path("reviews", views.ReviewsListView.as_view()),
path("reviews/favorite", views.AddFavoriteView.as_view()),
path("reviews/<int:pk>", views.SingleReviewView.as_view()),
Urls.py в папке проекта
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path("", include("reviews.urls")),
path("profiles/", include("profiles.urls"))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Settings.py
Одиночный отзыв HTML страница
{% extends "reviews/base.html" %}
{% block title %}Review Detail{% endblock %}
{% block content %}
<h1>{{ review.user_name }}</h1>
<p>Rating: {{ review.rating }} </p>
<p>{{ review.review_text }}</p>
<form action='/reviews/favorite' method='POST'>
{% csrf_token %}
<input type="hidden" name="review_id" value="{{ review.id }}" />
<button>Favorite</button>
</form>
{% endblock %}
В ответе на перенаправление HTTP следует использовать ведущую косую черту:
class AddFavoriteView(View):
def post(self, request):
print(request)
review_id = request.session['favorite_review'] = request.POST['review_id']
return HttpResponseRedirect(f'/reviews/{review_id}')
Если вы дадите пути имя, например:
path('reviews/<int:pk>', views.SingleReviewView.as_view(), name='review-details'),
тогда вы можете использовать redirect(…)
[Django-doc] для определения URL и возвращения правильного ответа HTTP перенаправления:
from django.shortcuts import redirect
class AddFavoriteView(View):
def post(self, request):
print(request)
review_id = request.session['favorite_review'] = request.POST['review_id']
return redirect('review-details', pk=review_id)