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

如何在Django模型的save方法中获取当前用户做权限校验?

解决Django模型仅超级用户可设置特定状态的问题

场景说明

你需要实现:仅超级用户能将Listing模型的status字段设为fake,普通用户无法操作。当前模型save方法无法获取当前认证用户,视图通过form.save(commit=False)后调用save()保存数据。


方案一:视图层直接校验(简单直观)

直接在视图里完成权限校验,无需修改模型:

@login_required
def create_listing(request):
    if request.method == 'POST':
        # 注意修正原代码中的拼写错误:ListingingForm → ListingForm
        form = ListingForm(request.POST)
        if form.is_valid():
            listing = form.save(commit=False)
            # 校验规则:状态为fake且当前用户不是超级用户时拦截
            if listing.status == 'fake' and not request.user.is_superuser:
                raise PermissionDenied("只有超级用户才能设置该状态")
            listing.save() 
            return redirect('booking_list') 
    else:
        form = ListingForm()
    return render(request, 'listings/create_listing.html', {'form': form})

优势:逻辑简单直接,无需改动模型,适合仅在单个视图调用保存的场景。


方案二:模型层校验(通用型强)

如果Listing模型会在多个视图或场景中被保存,建议将权限逻辑集中在模型层,需要给save方法传递用户参数:

1. 修改模型的save方法

from django.core.exceptions import PermissionDenied

class Listing(models.Model):
    STATUS_CHOICES = [
        ('available', 'Available'),
        ('rented', 'Rented'),
        ('unavailable', 'Unavailable'),
        ('fake', 'Fake'),
    ]

    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=200)
    description = models.TextField()
    status = models.CharField(max_length=12, choices=STATUS_CHOICES, default='available')

    def save(self, *args, user=None, **kwargs):
        # 校验:状态为fake时,必须传入超级用户
        if self.status == 'fake':
            if not user or not user.is_superuser:
                raise PermissionDenied("只有超级用户才能设置该状态")
        super().save(*args, **kwargs)

2. 在视图中调用save时传入当前用户

@login_required
def create_listing(request):
    if request.method == 'POST':
        form = ListingForm(request.POST)
        if form.is_valid():
            listing = form.save(commit=False)
            # 调用save时传入当前认证用户
            listing.save(user=request.user) 
            return redirect('booking_list') 
    else:
        form = ListingForm()
    return render(request, 'listings/create_listing.html', {'form': form})

优势:权限校验逻辑统一维护在模型,所有调用save的场景都会自动生效,避免重复编写校验代码。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:42:38