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

Django中按登录角色限制用户创建时Rol字段的选择权限

Django角色权限控制的CRUD实现问题

我正在Django中开发一套涉及jefe和encargado的CRUD系统,需求如下:

  • 管理员身份登录时,仅允许创建jefe角色的用户
  • jefe身份登录时,仅允许创建encargado角色的用户
  • jefe数据存储在自定义的usuarios表中,管理员使用Django自带的Admin面板

当前已实现管理员可见Rol字段,但需要进一步限制:管理员只能选择jefe角色,jefe只能选择encargado角色。


现有代码

模型代码

roles = (
    ('encargado', 'ENCARGADO'),
    ('jefe','JEFE'),
)

class Usuarios(models.Model): 
    id = models.BigAutoField(primary_key=True)
    nombre = models.CharField(max_length=30)
    rol = models.CharField(max_length=30, choices=roles, default='encargado')
    correo = models.CharField(max_length=30)
    contraseña = models.CharField(max_length=30)
    cedula = models.CharField(max_length=30)

    class Meta: 
        db_table = 'usuarios'

创建视图代码

class UsuarioCrear(SuccessMessageMixin, CreateView):
    model = Usuarios 
    form = Usuarios
    fields = "__all__"
    success_message = 'usuario creado correctamente !'
    
    def get_success_url(self):
        return reverse('leer')

创建页面HTML代码

<form method="post">
    {% csrf_token %}
    <!-- {{ form.as_p }} -->
    <div class="form-group">
        <label for="id" class="txt_negrita">Id</label>                                  
        {{ form.id|add_class:"form-control" }}
    </div>                                
    <div class="form-group">
        <label for="nombre" class="txt_negrita">Nombre</label>                                  
        {{ form.nombre|add_class:"form-control" }}
    </div>       
    {% if user.is_superuser %}
    <div class="form-group">
        <label for="rol" class="txt_negrita">Rol</label>
        {{ form.rol|add_class:"form-control"}}
    </div>
    {%endif%}
    <div class="form-group">
        <label for="correo" class="txt_negrita">Correo</label>
        {{ form.correo|add_class:"form-control" }}
    </div>
    <div class="form-group">
        <label for="contraseña" class="txt_negrita">Contraseña</label>
        {{ form.contraseña|add_class:"form-control" }}
    </div>
    <div class="form-group">
        <label for="cedula" class="txt_negrita">Cedula</label>
        {{ form.cedula|add_class:"form-control" }}
    </div> 
    <button type="submit" class="btn btn-primary">Aceptar</button>
    <a href="../" type="submit" class="btn btn-danger">Cancelar</a>
</form>

解决方案

1. 自定义表单类,动态过滤角色选项

创建自定义表单,根据当前登录用户身份限制角色可选范围:

from django import forms
from .models import Usuarios, roles

class UsuarioForm(forms.ModelForm):
    class Meta:
        model = Usuarios
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        super().__init__(*args, **kwargs)
        
        if self.user:
            # 管理员仅能选择jefe
            if self.user.is_superuser:
                self.fields['rol'].choices = [('jefe', 'JEFE')]
            # Jefe仅能选择encargado
            elif self.user.rol == 'jefe':
                self.fields['rol'].choices = [('encargado', 'ENCARGADO')]

    def clean_rol(self):
        # 后端二次验证,防止恶意提交
        rol = self.cleaned_data.get('rol')
        if self.user.is_superuser and rol != 'jefe':
            raise forms.ValidationError("管理员只能创建jefe角色的用户")
        if self.user.rol == 'jefe' and rol != 'encargado':
            raise forms.ValidationError("Jefe只能创建encargado角色的用户")
        return rol

2. 修改视图,传递当前用户到表单

更新视图类,在实例化表单时传入当前登录用户:

class UsuarioCrear(SuccessMessageMixin, CreateView):
    model = Usuarios 
    form_class = UsuarioForm  # 使用自定义表单
    success_message = 'usuario creado correctamente !'
    
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user  # 传递当前用户到表单
        return kwargs
    
    def get_success_url(self):
        return reverse('leer')

3. 调整HTML模板,显示对应角色字段

修改模板,让jefe用户也能看到角色字段(此时选项已被限制为encargado):

<form method="post">
    {% csrf_token %}
    <div class="form-group">
        <label for="id" class="txt_negrita">Id</label>                                  
        {{ form.id|add_class:"form-control" }}
    </div>                                
    <div class="form-group">
        <label for="nombre" class="txt_negrita">Nombre</label>                                  
        {{ form.nombre|add_class:"form-control" }}
    </div>       
    {% if user.is_superuser or user.rol == 'jefe' %}
    <div class="form-group">
        <label for="rol" class="txt_negrita">Rol</label>
        {{ form.rol|add_class:"form-control"}}
    </div>
    {% endif %}
    <div class="form-group">
        <label for="correo" class="txt_negrita">Correo</label>
        {{ form.correo|add_class:"form-control" }}
    </div>
    <div class="form-group">
        <label for="contraseña" class="txt_negrita">Contraseña</label>
        {{ form.contraseña|add_class:"form-control" }}
    </div>
    <div class="form-group">
        <label for="cedula" class="txt_negrita">Cedula</label>
        {{ form.cedula|add_class:"form-control" }}
    </div> 
    <button type="submit" class="btn btn-primary">Aceptar</button>
    <a href="../" class="btn btn-danger">Cancelar</a>
</form>

额外说明

  • 确保当前登录的jefe用户能通过self.request.user.rol获取角色,可通过自定义用户认证后端或关联Django User模型与自定义Usuarios表实现。
  • 后端验证是必须的,避免前端被篡改后提交非法数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 12:35:20