如何在Django的forms.py中基于Permission模型创建权限布尔字段表单?
动态生成权限表单的实现方案
要匹配模板里的动态权限复选框,我们需要在表单中动态生成对应字段——因为app名称(比如ticket、users)是从Permission模型中来的,无法提前硬编码。具体实现步骤如下:
1. 编写动态表单类
在forms.py中创建表单,通过重写__init__方法,根据Permission模型中的app动态添加四个BooleanField:
from django import forms from .models import Permission class PermissionForm(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 获取所有唯一的app名称,避免重复处理同一个app app_list = Permission.objects.values_list('app', flat=True).distinct() for app in app_list: # 为每个app添加四个权限字段,字段名和模板中的name属性严格对应 self.fields[f"{app}_add"] = forms.BooleanField( label=f"{app} - 添加", required=False, widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': f"{app}ManagementWrite"}) ) self.fields[f"{app}_read"] = forms.BooleanField( label=f"{app} - 读取", required=False, widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': f"{app}ManagementRead"}) ) self.fields[f"{app}_update"] = forms.BooleanField( label=f"{app} - 更新", required=False, widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': f"{app}ManagementUpdate"}) ) self.fields[f"{app}_delete"] = forms.BooleanField( label=f"{app} - 删除", required=False, widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': f"{app}ManagementDelete"}) ) # 编辑场景下设置初始值(示例:从Permission模型读取已有权限) if self.initial: perm_obj = Permission.objects.filter(app=app).first() if perm_obj: self.fields[f"{app}_add"].initial = perm_obj.add self.fields[f"{app}_read"].initial = perm_obj.read self.fields[f"{app}_update"].initial = perm_obj.update self.fields[f"{app}_delete"].initial = perm_obj.delete
2. 视图中使用表单
在视图里,先获取Permission模型的对象列表传递给模板(和现有模板逻辑一致),同时实例化表单处理请求:
from django.shortcuts import render from .forms import PermissionForm from .models import Permission def permission_management(request): permissions = Permission.objects.all() if request.method == 'POST': form = PermissionForm(request.POST) if form.is_valid(): # 处理表单提交的权限数据 for app in Permission.objects.values_list('app', flat=True).distinct(): # 提取每个app的四个权限值 add_perm = form.cleaned_data.get(f"{app}_add", False) read_perm = form.cleaned_data.get(f"{app}_read", False) update_perm = form.cleaned_data.get(f"{app}_update", False) delete_perm = form.cleaned_data.get(f"{app}_delete", False) # 更新Permission模型中的权限记录 Permission.objects.filter(app=app).update( add=add_perm, read=read_perm, update=update_perm, delete=delete_perm ) # 这里可以添加跳转或提示信息 else: # 初始化表单初始值(编辑场景) initial_data = {} for perm in permissions: initial_data[f"{perm.app}_add"] = perm.add initial_data[f"{perm.app}_read"] = perm.read initial_data[f"{perm.app}_update"] = perm.update initial_data[f"{perm.app}_delete"] = perm.delete form = PermissionForm(initial=initial_data) return render(request, 'your_template.html', {'permissions': permissions, 'form': form})
3. 模板适配(可选优化)
如果想减少模板硬编码,可以把手动写的input标签替换为Django表单的渲染方式,自动关联字段属性:
{% for item in permissions %} <tr> <td class="text-nowrap">{{ item.app }}</td> <td> <div class="d-flex"> <div class="form-check me-3 me-lg-5 mb-0 mt-0"> {{ form[item.app+'_add'] }} <label class="form-check-label" for="{{ item.app }}ManagementWrite">add</label> </div> <div class="form-check me-3 me-lg-5 mb-0 mt-0"> {{ form[item.app+'_read'] }} <label class="form-check-label" for="{{ item.app }}ManagementRead">read</label> </div> <div class="form-check me-3 me-lg-5 mb-0 mt-0"> {{ form[item.app+'_update'] }} <label class="form-check-label" for="{{ item.app }}ManagementUpdate">update</label> </div> <div class="form-check mb-0 mt-0"> {{ form[item.app+'_delete'] }} <label class="form-check-label" for="{{ item.app }}ManagementDelete">delete</label> </div> </div> </td> </tr> {% endfor %}
这样表单和模板就能完全对应,既保留了原有UI样式,又能利用Django表单的验证、初始化功能。
内容的提问来源于stack exchange,提问作者Alireza javanpour
相关产品推荐
相关产品推荐

