Django后台自定义权限失效:授权用户登录后下拉列表无选项
问题排查与解决方案
1. 先确认权限是否真的存在且匹配
先排查权限的核心匹配问题:
- 你在视图里生成权限codename的逻辑是
f'can_see_{position[1].replace(" ", "_").lower()}',对应Position 1生成的是can_see_position_1,和表单里判断的portal.can_see_position_1的codename部分一致,但要确认app名称是否正确(这里是portal)。 - 打开Django Shell执行以下命令验证权限:
from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType from portal.models import Main # 替换成你的Main模型路径 ct = ContentType.objects.get_for_model(Main) print(Permission.objects.filter(codename='can_see_position_1', content_type=ct).exists()) print(Permission.objects.filter(codename='can_see_position_2', content_type=ct).exists())
如果输出不是True True,说明权限没创建成功。
2. 修正权限创建的位置
你把权限创建代码直接写在views.py顶层,会导致每次请求都执行,还可能在模型迁移前运行导致报错。改用post_migrate信号来创建:
# 在你的app下新建signals.py from django.db.models.signals import post_migrate from django.dispatch import receiver from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType from .models import Main @receiver(post_migrate) def create_position_permissions(sender, **kwargs): if sender.name == 'portal': # 替换成你的app名称 ct = ContentType.objects.get_for_model(Main) for position in Main.positions: codename = f'can_see_{position[1].replace(" ", "_").lower()}' name = f'Can see {position[1]}' if not Permission.objects.filter(codename=codename, content_type=ct).exists(): Permission.objects.create( codename=codename, name=name, content_type=ct )
然后在app的apps.py里注册信号:
from django.apps import AppConfig class PortalConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'portal' def ready(self): import portal.signals # 对应你的signals路径
执行python manage.py migrate触发信号,确保权限被正确创建。
3. 检查用户权限分配
进入Django后台,确认用户确实被分配了portal | main | Can see Position 1和portal | main | Can see Position 2这两个权限(注意权限的内容类型是Main模型)。
4. 临时调试验证用户权限
在视图里加一行调试代码,确认当前登录用户的权限状态:
@login_required(login_url='login') def view_input(request): # 临时调试,看控制台输出 print(request.user.has_perm('portal.can_see_position_1')) print(request.user.has_perm('portal.can_see_position_2')) # 原有代码 if request.method == 'POST': form = main_input(request.POST or None, user=request.user) # ... 剩余代码
如果控制台输出是False,说明用户权限没分配对;如果是True,再排查表单逻辑。
5. 优化表单初始化逻辑(可选)
可以简化表单里的权限判断,避免重复检查self.user:
def __init__(self, *args, **kwargs): self.user = kwargs.pop('user', None) super(main_input, self).__init__(*args, **kwargs) allowed_positions = [] if self.user: if self.user.has_perm('portal.can_see_position_1'): allowed_positions.append(('1', 'Position 1')) if self.user.has_perm('portal.can_see_position_2'): allowed_positions.append(('2', 'Position 2')) if self.user.has_perm('portal.can_see_position_3'): allowed_positions.append(('3', 'Position 3')) # 可选:添加默认提示选项,避免下拉完全空白 if not allowed_positions: allowed_positions.append(('', '无可用职位')) self.fields['drop_down'].choices = allowed_positions
内容的提问来源于stack exchange,提问作者motylas
相关产品推荐
相关产品推荐

