自定义Django AdminModel视图
在我的Django应用中,我为所有未注册的用户创建了Guest
用户账户(它们的邮箱都是'guest@mysite.com')。同时,我还为这些Guest账户创建了一些演示对象。这些对象和注册用户的对象在同一个表里(也就是同一个模型)。而且,我有不止一种类型(模型)的这些对象,比如:
class Object1(models.Model):
user = ForeignKey(...)
...
class Object2(models.Model):
user = ForeignKey(...)
...
我想要实现的目标是,当我在django管理后台查看这些对象时,能够过滤掉所有与Guest账户相关的对象。
目前,我是通过子类化django.contrib.admin.views.main.ChangeList
,并重写get_query_set
方法来排除这些对象的,同时在运行时重新定义了django的ModelAdmin类的get_changelist
方法:
class FilteredChangeList(ChangeList):
def get_query_set(self):
qs = super(FilteredChangeList, self).get_query_set()
if is_related_to(self.model, Profile):
qs = qs.exclude(user__email='guest@mysite.com')
return qs
def my_getchangelist(self, request, **kwargs):
return FilteredChangeList
ModelAdmin.get_changelist = my_getchangelist
我觉得在运行时重新定义django的方法可能不是个好做法,那么有没有什么正确的解决方案呢?
3 个回答
你可以创建一个新的类,继承自 ModelAdmin
,并且重写 get_changelist
这个方法,而不是在运行时重新定义它。
class FilteredModelAdmin(ModelAdmin):
def get_changelist(self, request, **kwargs):
return FilteredChangeList
然后,用 FilteredModelAdmin
来注册你的模型,而不是用 ModelAdmin
。
admin.site.register(Object1, FilteredModelAdmin)
admin.site.register(Object2, FilteredModelAdmin)
如果你需要为你的模型自定义其他设置,可以继承 FilteredModelAdmin
,而不是 ModelAdmin
。
class Object1ModelAdmin(FilteredModelAdmin)
# other customizations here
admin.site.register(Object1, Object1ModelAdmin)
你还可以使用代理模型。比如,你可以有一个模型是用来表示“真实”用户的,另一个模型则用来表示“访客”用户的。
看起来你可能做了很多不必要的工作。你可以自己创建一个 ModelAdmin
类,并重写它的 queryset
方法,这样就不需要自己构建一个 ChangeList
类了。
class MyFilteredAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = super(MyFilteredAdmin, self).queryset(request)
if is_related_to(self.model, Profile):
qs = qs.exclude(user__email='guest@mysite.com')
return qs
然后你可以直接用这个新的管理类来注册你的模型,比如 admin.site.register(Model, MyFilteredAdmin)
,或者创建一些子类,让它们继承自 MyFilteredAdmin
,而不是直接继承自 Django 的 ModelAdmin
。