如何在Django Admin中重写新增字段集QuerySet并优化权限查询
解决Django Admin新增用户时权限查询过多的问题
核心方案:自定义用户创建表单,预取权限关联数据
1. 自定义用户创建表单
继承Django内置的UserCreationForm,在表单初始化时重写permissions字段的查询集,通过select_related预取权限关联的content_type——这是触发大量N+1查询的核心原因,默认加载权限时会逐个查询对应的ContentType。
示例代码:
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User, Permission class CustomUserCreationForm(UserCreationForm): class Meta: model = User fields = UserCreationForm.Meta.fields + ('permissions',) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 预取权限关联的content_type,将查询量从数百次压缩到1-2次 self.fields['permissions'].queryset = Permission.objects.select_related('content_type').order_by('name')
2. 在UserAdmin中绑定自定义表单
自定义UserAdmin类(或修改已有类),将add_form属性指定为上面的自定义表单,同时确保新增用户的字段集包含permissions。
示例代码:
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin class UserAdmin(BaseUserAdmin): add_form = CustomUserCreationForm # 配置新增用户的字段集,确保permissions字段可见 add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('username', 'password1', 'password2', 'permissions'), }), ) # 替换默认的UserAdmin注册 admin.site.unregister(User) admin.site.register(User, UserAdmin)
额外说明
- 如果你的权限还关联其他模型,可以叠加
prefetch_related处理多对多/反向关联的预取需求。 - 该方案无需依赖
get_queryset方法,直接在表单层面修改权限的查询集,完美适配新增用户的场景。
内容的提问来源于stack exchange,提问作者Ali Hassan
相关产品推荐
相关产品推荐

