You need to enable JavaScript to run this app. 如何在Django中实现指定字段仅超级用户可编辑、普通用户只读
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中实现指定字段仅超级用户可编辑、普通用户只读

实现方案

以下针对不同使用场景分别给出实现方式:

1. Django Admin 后台权限控制

通过重写ModelAdmin的get_readonly_fields方法实现字段权限控制:

from django.contrib import admin
from .models import QuestionModel

class QuestionModelAdmin(admin.ModelAdmin):
    def get_readonly_fields(self, request, obj=None):
        # 非超级用户访问时,将answer字段加入只读列表
        if not request.user.is_superuser:
            return self.readonly_fields + ('answer',)
        return self.readonly_fields

admin.site.register(QuestionModel, QuestionModelAdmin)

2. 普通表单/类视图场景

首先自定义ModelForm,在初始化时根据当前用户权限设置字段是否禁用:

from django import forms
from .models import QuestionModel

class QuestionModelForm(forms.ModelForm):
    class Meta:
        model = QuestionModel
        fields = '__all__'
    
    def __init__(self, *args, **kwargs):
        # 从参数中获取当前登录用户
        user = kwargs.pop('user', None)
        super().__init__(*args, **kwargs)
        if user and not user.is_superuser:
            # 设置answer字段为禁用,Django会自动忽略该字段的提交值,避免前端篡改绕过
            self.fields['answer'].disabled = True

在视图中传递当前用户给表单即可,以通用更新视图为例:

from django.views.generic.edit import UpdateView
from .models import QuestionModel
from .forms import QuestionModelForm

class QuestionUpdateView(UpdateView):
    model = QuestionModel
    form_class = QuestionModelForm
    success_url = '/questions/'

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        # 将当前登录用户传入表单
        kwargs['user'] = self.request.user
        return kwargs

3. Django REST Framework 接口场景

通过自定义序列化器的字段属性实现权限控制:

from rest_framework import serializers
from .models import QuestionModel

class QuestionModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = QuestionModel
        fields = '__all__'
    
    def get_fields(self):
        fields = super().get_fields()
        request = self.context.get('request')
        # 非超级用户调用接口时,将answer字段设为只读
        if request and not request.user.is_superuser:
            fields['answer'].read_only = True
        return fields

4. 模型层兜底校验

为了避免业务代码绕过视图层直接修改answer字段,可以重写模型的save方法做最终校验:

class QuestionModel(models.Model):
    # 原有字段定义保持不变
    question = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    doubt_class_id = models.ForeignKey(DoubtClasses, on_delete=models.CASCADE, null=True, blank=True)
    conceptual_class_id = models.ForeignKey(LiveClass_details, on_delete=models.CASCADE, null=True, blank=True)
    mentor = models.ForeignKey(Mentor, on_delete=models.CASCADE, null=True, blank=True)
    answer = models.TextField(default='')

    def save(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        # 非超级用户更新已有实例时,强制保持原有answer值不变
        if self.pk and user and not user.is_superuser:
            original_obj = QuestionModel.objects.get(pk=self.pk)
            self.answer = original_obj.answer
        super().save(*args, **kwargs)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 16:06:03