Django如何根据登录用户限制Admin表单中User外键字段的可选值
Django Admin 按登录用户限制外键可选值的实现方法
你之前的写法存在两个核心问题:
- ModelForm 初始化默认不会传入request对象,擅自修改
__init__的入参签名会导致参数匹配错误 - 外键字段的
queryset属性必须接收查询集对象,不能直接赋值单个用户实例
下面提供两种可行实现方案:
方案一:通过Admin内置钩子实现(推荐,无需自定义Form)
Django的ModelAdmin自带formfield_for_foreignkey钩子,可直接在该方法内对外键选项做过滤,方法本身自带request参数无需额外传递:
from django.contrib import admin from .models import Client class ClientAdmin(admin.ModelAdmin): def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "user": # 仅保留当前登录用户作为可选选项 kwargs["queryset"] = request.user.__class__.objects.filter(id=request.user.id) return super().formfield_for_foreignkey(db_field, request, **kwargs) admin.site.register(Client, ClientAdmin)
方案二:自定义ModelForm实现
如果需要保留自定义Form的逻辑,需要先在Admin层将request传入Form的初始化参数:
1. 修正自定义Form代码
class ClientAdminForm(forms.ModelForm): class Meta: model = Client fields = "__all__" def __init__(self, *args, **kwargs): # 从kwargs中取出传入的request对象 self.request = kwargs.pop("request", None) super().__init__(*args, **kwargs) if self.request: # 给queryset赋值过滤后的用户查询集 self.fields['user'].queryset = self.request.user.__class__.objects.filter(id=self.request.user.id)
2. 在Admin中注入request到Form参数
from django.contrib import admin from .models import Client from .forms import ClientAdminForm class ClientAdmin(admin.ModelAdmin): form = ClientAdminForm # 重写方法将request传入Form的初始化参数 def get_form_kwargs(self, request, obj=None, **kwargs): form_kwargs = super().get_form_kwargs(request, obj, **kwargs) form_kwargs["request"] = request return form_kwargs admin.site.register(Client, ClientAdmin)
内容的提问来源于stack exchange,提问作者Agung
相关产品推荐
相关产品推荐

