Django UpdateView权限控制逻辑修正及对象获取方法咨询
Great question! Let's fix your permission logic and clarify the get_object() confusion step by step.
First, Let's Fix the Permission Logic
Your current approach has two main issues:
- You're repeating permission checks in both
test_func()andform_valid(), which is redundant and error-prone (yourform_valid()has an emptyelseclause that would cause a server error if the user lacks permission). - The query to check group membership is inefficient—you don't need to fetch all users in the group; you can directly check the current user's groups.
Key Notes:
UserPassesTestMixinrunstest_func()before any form processing, so if the user fails the test, they'll get a 403 Forbidden response immediately (no need to re-check inform_valid()).- Checking
self.request.user.groups.filter(name=...).exists()is far more efficient than querying all users in the group and checking membership.
Fixed StoryUpdateView Code
# views.py from django.urls import reverse_lazy from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.views.generic.edit import UpdateView from .models import Story class StoryUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): model = Story # Important: Your model uses `story` as the content field, not `content`—fix this! fields = ['title', 'story'] # Add a success URL (required if your Story model doesn't have get_absolute_url()) success_url = reverse_lazy('your-success-page-name') def test_func(self): # Get the story object using the view's built-in get_object() method story = self.get_object() # Check if current user is in the group matching the story's page name return self.request.user.groups.filter(name=story.page.name).exists() # You only need form_valid() if you want to add extra save logic (e.g., set an editor) def form_valid(self, form): # Optional: Add custom logic here, like tracking who edited the story # form.instance.updated_by = self.request.user return super().form_valid(form)
About self.get_object() vs get_object_or_404()
self.get_object() is the correct and recommended way to fetch the story in this CBV context:
- It's a method provided by
SingleObjectMixin(whichUpdateViewinherits from) that automatically retrieves the object using thepkfrom your URL. - It handles the "object not found" case by raising an
Http404exception, which Django converts to a proper 404 page—no need to useget_object_or_404()manually. - It's cleaner and aligns with Django's CBV design principles, avoiding redundant code like manually parsing
self.kwargs['pk'].
Additional Tips
- If you want a custom message when users lack permission, override
handle_no_permission():from django.http import HttpResponseForbidden def handle_no_permission(self): if self.request.user.is_authenticated: return HttpResponseForbidden("You don't have permission to edit this story.") # Let LoginRequiredMixin handle redirecting unauthenticated users to login return super().handle_no_permission() - Double-check your
fieldsattribute—yourStorymodel has astorytext field, but your original code usedcontent, which would cause a validation error.
内容的提问来源于stack exchange,提问作者fpaekoaij
相关产品推荐
相关产品推荐

