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

Django自定义组表单权限保存后被save_m2m()清空的问题

解决Django Group表单权限被save_m2m清空的问题

问题根源在于Django ModelForm的默认执行流程:当调用父类save(commit=True)时,会自动触发save_m2m()方法。而你的表单里permissions字段的queryset被设为空集合,save_m2m会把这个空集合同步到Group的权限关联中,直接覆盖你手动设置的权限。

要解决这个问题,只需做两个关键修改:

  • 重写表单的save_m2m方法,跳过对permissions字段的处理
  • 调整save方法逻辑,避免和父类流程冲突

修改后的完整代码:

class CustomGroupForm(forms.ModelForm):
    env_name = forms.CharField(max_length=100, required=False)
    schema_name = forms.CharField(max_length=100, required=False)

    class Meta:
        model = Group
        fields = ['name', 'permissions', 'env_name', 'schema_name']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 保持空queryset,避免页面显示无关权限选项
        self.fields['permissions'].queryset = Permission.objects.none()

    def save(self, commit=True):
        # 先调用父类save(commit=False)获取未保存的group实例
        group = super().save(commit=False)
        
        name = self.cleaned_data.get('name', '')
        prefix = name
        logger.info(f'Prefix 1: {prefix}')
        
        filtered_permissions = Permission.objects.filter(
            content_type__app_label__startswith=prefix
        )
        
        if commit:
            # 先保存group实例以获取ID
            group.save()
            # 设置过滤后的权限,set()方法会直接持久化关联关系
            group.permissions.set(filtered_permissions)
        
        return group

    def save_m2m(self):
        # 重写save_m2m,跳过permissions字段的处理
        excluded_fields = ['permissions']
        for field_name, field in self.fields.items():
            if field_name in excluded_fields:
                continue
            # 仅处理其他可能存在的多对多字段
            if isinstance(field, forms.ModelMultipleChoiceField) and hasattr(self.instance, field_name):
                setattr(
                    self.instance,
                    field_name,
                    self.cleaned_data.get(field_name, [])
                )

核心说明:

  1. 重写save_m2m:默认的save_m2m会处理所有多对多字段,跳过permissions后,就不会让空集合覆盖我们手动设置的权限。
  2. 优化save逻辑:group.permissions.set()方法本身会直接保存关联关系,无需额外调用group.save()。
  3. 保留空queryset:确保Admin页面的权限选择框不会显示多余选项,符合你通过代码自动分配权限的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:20:03