Django自定义admin界面 - Part 1

2009-11-17 21:31

记录下前段时间折腾这个问题时的一些经历, 希望对其他人有帮助, 好吧, 至少对我这个记性很差的人是有帮助的. 首先是相关资料的链接:
  1. 官方admin文档
  2. 一个关于这个主题的Slide
  3. IBM DevWorks上的一篇文章
  4. luke一篇稍有点旧的文章
我的需要比较特殊一点, 首先是有在链接4中介绍的row级别的权限控制, 然后有3中介绍的根据用户权限而给出不同的row. 还有些其他的需求, 我会在后面慢慢给出.

简单自定义项目

这个大都是看看官方文档, 稍稍实验就能成功, 不用override默认方法就能搞定的一大类自定义. 不过不要忽视这一类自定义. 虽然这一类很简单, 但是给用户带来的体验改变是很直接的. 举几个典型的例子:
  1. 用list_filter来帮助用户快速找到自己所需的内容, 典型的例子是在一群用户中速度找到staff和超级用户.
  2. 用list_display来列表显示各个项目的情况, 例如用户个人档案页面中能够详细给出用户的姓名, 电子邮件和手机号等等
注意到这儿有一个小的hack. 熟悉Django的用户都知道, 电子邮件实际上是User模型的一部分, 我们自己定义Userprofile模型时一般不再会重新定义email这个域. 为了在list_display中能够显示用户的电子邮件, 很自然的想法可能是写成:
list_display = ('username', 'realname', 'cell_number', 'user__email')
但需要注意的是, list_display不能接受这种跨模型的查询. 因此上面的写法(据我测试)是不能成功显示用户电子邮件的. 而由于list_display能接受模型的方法作为参数, 因此我们需要在Userprofile模型中额外定义一个名为email的方法:
def email(self):
"""
    This function would return the email of the user of the profile.
    """
return self.user.email
接下来我们在list_display中添加一个名为'email'的字符串即可.

row级别的权限控制

这个的实现原理是在相关数据模型中添加一列, 记录这个模型的创建者. 然后在保存模型时记录下request.user, 保存在这个新添加的Field中. 然后, 为了让用户只看到自己创建的数据, 修改ModelAdmin的queryset方法. 添加一个filter来限制用户所能看到的内容:
class DocumentAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = super(DocumentAdmin, self).queryset(request)
# If super-user, show all comments
if request.user.is_superuser:
return qs
return qs.filter(added_by=request.user)
在上面的代码中, 可以看到第三行的super调用了父类的方法, 即给出原来应产生的QuerySet, 然后根据用户权限的不同做了进一步的过滤. 上面说的基本上是在复述3中对这个方法的论述. 简单地说, 这一段所提供的最直接的信息点是, 为了让登陆到admin界面的用户看到或看不到某些内容, 可以通过修改默认的queryset方法来实现. 而且queryset方法接受的参数中包括用户(request.user). 因此, 要定义自己的过滤方法是相当容易的. 在我手头的应用中, 我同样修改了这个方法, 虽然我不需要实现对row级别的权限控制, 但是无疑这一思路是很有用的.