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
相关产品推荐
相关产品推荐

