get_form_class()
函数是Django中的一个方法,主要用于自定义Admin中表单的配置。当Admin的配置中使用了form
或formfield_overrides
字段时,Django会自动调用get_form_class()
方法来获取表单类。这个方法的作用就是返回一个表单类,该表单类将被用来在Admin中管理相应的数据模型。
以下是get_form_class()
方法的调用方式:
class MyModelAdmin(admin.ModelAdmin):
form = MyCustomForm # 调用MyCustomForm定义的自定义表单
def get_form_class(self, request, obj=None, **kwargs):
"""
获取表单类的方法。
:param request: HttpRequest对象。
:param obj: 当前编辑对象。
:param kwargs: 其他可选参数。
:return: 一个表单类。
"""
if obj is None:
return MyAddForm # 创建新纪录时调用MyAddForm定义的表单。
else:
return MyEditForm # 编辑已有纪录时调用MyEditForm定义的表单。
其中request
参数是当前请求的HttpRequest
对象,obj
参数用于表示当前编辑的对象实例。当创建新的对象实例时,obj
为None
,否则obj
为对应的数据库对象实例。
以下是两个使用get_form_class()
方法的实例:
- 根据用户类型生成不同的表单类
假设我们的网站有两种用户类型:普通用户和管理员用户。普通用户只能够对自己的个人信息进行编辑,而管理员用户可以编辑所有用户的信息。因此,我们需要根据当前登录的用户类型来生成不同的表单类:
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.admin.views.decorators import staff_member_required
from django.utils.decorators import method_decorator
from django.forms import ModelForm
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
class AdminUserProfileForm(ModelForm):
class Meta:
model = UserProfile
class UserProfileAdmin(admin.ModelAdmin):
model = UserProfile
def get_form_class(self, request, obj=None, **kwargs):
user = request.user
if user.has_perm('auth.change_user'):
return AdminUserProfileForm
return UserProfileForm
@method_decorator(login_required)
@method_decorator(user_passes_test(lambda u: u.is_staff))
def changelist_view(self, request, extra_context=None):
return super().changelist_view(request, extra_context)
@method_decorator(login_required)
@method_decorator(staff_member_required)
def add_view(self, request, extra_context=None):
return super().add_view(request, extra_context)
在这个例子中,我们定义了两个表单类:UserProfileForm
和AdminUserProfileForm
。前者用于普通用户,后者用于管理员用户。通过user.has_perm('auth.change_user')
判断当前用户是否有权限对所有用户信息进行修改。如果有,返回AdminUserProfileForm
,否则返回普通用户表单类UserProfileForm
。
另外,在视图函数中我们使用了Django的登录装饰器和user_passes_test
装饰器来限制用户访问权限。login_required
装饰器用于限制必须登录才能访问changelist_view
和add_view
方法。
- 实现联动表单
假设我们的网站有一个需求:在编辑某个页面时,需要根据当前选中的一级分类,动态生成对应的二级分类下拉框。此时我们就可以使用get_form_class()
方法来实现这个需求:
class ProductForm(ModelForm):
class Meta:
model = Product
class ProductAdmin(admin.ModelAdmin):
form = ProductForm
def get_form_class(self, request, obj=None, **kwargs):
form_class = super().get_form_class(request, obj, **kwargs)
class MyProductForm(form_class):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['category2'].widget.choices = self.get_category2_choices()
def get_category2_choices(self):
"""
动态生成category2下拉框的选项。
"""
if self.instance is None or self.instance.category is None:
return []
return ((c.id, c.name) for c in self.instance.category.category2_set.all())
return MyProductForm
在这个例子中,我们首先定义了一个ProductForm
表单类。在get_form_class()
方法中,我们首先调用super()
方法来获取原始的表单类。然后定义一个内部类MyProductForm
继承原始的表单类。在MyProductForm
中,我们重写了__init__()
方法,在方法中动态设置了二级分类下拉框的选项。
重要的是,我们在获取数据集的时候使用了ORM的链式查询。最终返回的选择元组是一个迭代器。