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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:47:34