You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何解决Django中POST请求出现405 Method Not Allowed错误?

Hey there, let's dig into your 405 Method Not Allowed issue with the vote submission. I spot a few key issues in your code that are likely causing this—let's break them down one by one:

1. Template Variable Typo (Most Likely Culprit)

Look at your HTML template: you're using {{vote_form_url}} as the form's action, but in your MovieDetail view, you're passing the URL as vote_url_form (note the underscore placement difference).

<!-- Your template has this (wrong variable name) -->
<form action="{{vote_form_url}}" method="post" enctype="multipart/form-data">
# Your MovieDetail view sets this (correct variable name)
ctx['vote_url_form'] = vote_url_form

Since the variable name doesn't match, the form's action is empty, which means it submits the POST request to the current page's URL—movie/<int:pk>/—which is handled by MovieDetail, a DetailView that only accepts GET requests by default. That's exactly why you're getting a 405 error.

Fix: Correct the template variable to match what you're passing from the view, and remove the unnecessary enctype (your form doesn't handle file uploads):

<form action="{{vote_url_form}}" method="post">

2. Unnecessary Override of render_to_response in UpdateVote

Your UpdateVote view overrides render_to_response, but this method is meant for rendering responses during GET requests (like loading an edit form). For POST requests, UpdateView already uses get_success_url to redirect after a successful submission.

Your current override forces a redirect even for GET requests, breaking the normal view flow. Plus, you're using the Vote's ID instead of the Movie's ID in the redirect (you already have the correct logic in get_success_url).

Fix: Remove the entire render_to_response method from UpdateVote—your existing get_success_url is already doing what you need, and the default behavior will work correctly.

3. URL Consistency Issue

Your UpdateVote URL pattern doesn't end with a slash, while CreateVote does:

# CreateVote (ends with slash)
path('movie/<int:movie_id>/vote/', CreateVote.as_view(), name='create_vote'),
# UpdateVote (no trailing slash)
path('movie/<int:movie_id>/vote/<int:pk>', UpdateVote.as_view(), name='UpdateVote'),

While Django's APPEND_SLASH setting might handle this automatically, it's better to keep patterns consistent. Add a trailing slash to the UpdateVote URL:

path('movie/<int:movie_id>/vote/<int:pk>/', UpdateVote.as_view(), name='UpdateVote'),

4. Improve Security in UpdateVote

Right now, you fetch all Vote objects first then check ownership in get_object. A better practice is to filter the queryset to only include the current user's votes upfront, so unauthorized users can't even access other users' votes:

class UpdateVote(LoginRequiredMixin, UpdateView):
    form_class = VoteForm
    # Remove the global queryset
    # queryset = Vote.objects.all()

    def get_queryset(self):
        # Only return votes belonging to the current user
        return Vote.objects.filter(user=self.request.user)

    def get_object(self, queryset=None):
        vote = super().get_object(queryset)
        # This check is now redundant but can stay for extra safety
        if vote.user != self.request.user:
            raise PermissionDenied('can not change another user vote')
        return vote

    # Keep your existing get_success_url
    def get_success_url(self):
        movie_id = self.object.movie.id
        return reverse('core:movie_detail', kwargs={'pk':movie_id})

Final Checks

After making these changes, test your flow again:

  • Log in as a user
  • Navigate to a movie detail page
  • Submit a vote (create or update)
  • You should be redirected back to the movie detail page without the 405 error.

Let me know if you still run into issues after these fixes!

内容的提问来源于stack exchange,提问作者Sanjay

火山引擎 最新活动