You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. You're repeating permission checks in both test_func() and form_valid(), which is redundant and error-prone (your form_valid() has an empty else clause that would cause a server error if the user lacks permission).
  2. 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:

  • UserPassesTestMixin runs test_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 in form_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 (which UpdateView inherits from) that automatically retrieves the object using the pk from your URL.
  • It handles the "object not found" case by raising an Http404 exception, which Django converts to a proper 404 page—no need to use get_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 fields attribute—your Story model has a story text field, but your original code used content, which would cause a validation error.

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 10:37:33