ModelAdmin是admin应用中最经常使用的一个类,最终效果都将在这个类中体现出来。总的来讲,这个类能够完成如下功能:html
单个对象(object)的操做:建立(add)、修改(change)、删除(delete)python
结果集(queryset)的操做:查看(display)、搜索(search)、过滤(filter)、分页(paginator)、排序(sort)git
权限控制:增删改查、自定义权限github
每一个modelAdmin有四个页面,添加页面(add)、修改页面(change)、列表页面(changelist)、历史页面(history),每一个页面含有本身特定的区域,称之为block。使用ModelAdmin自定义各个block的内容和位置。数据库
admin应用和普通Django同样,也有本身的urls模块、views模块、template前台模板,记住它们的规则是很是必要的。urls-views-template对应关系在定义在django.contrib.admin.options.ModelAdmin的get_urls方法中。django
def get_urls(self): from django.conf.urls import patterns, url def wrap(view): def wrapper(*args, **kwargs): return self.admin_site.admin_view(view)(*args, **kwargs) return update_wrapper(wrapper, view) info = self.model._meta.app_label, self.model._meta.module_name urlpatterns = patterns('', url(r'^$', wrap(self.changelist_view), name='%s_%s_changelist' % info), url(r'^add/$', wrap(self.add_view), name='%s_%s_add' % info), url(r'^(.+)/history/$', wrap(self.history_view), name='%s_%s_history' % info), url(r'^(.+)/delete/$', wrap(self.delete_view), name='%s_%s_delete' % info), url(r'^(.+)/$', wrap(self.change_view), name='%s_%s_change' % info), ) return urlpatterns
摘自:https://github.com/django/django/blob/master/django/contrib/admin/options.py app
使用admin.site.register方法将ModelAdmin和Model关联起来,每一个model只能拥有一个ModelAdmin与之关联,关联以后在ModelAdmin中可使用self.model访问该model,ModelAmin方法的obj参数也是指的这个model。Model能够是一个代理模型类,使用方法参见这里proxy model。ide
ModelAdmin对于同一个选项一般有静态(成员变量形式)和动态(成员方法形式)两种不一样的方式,且后者具备更高的优先级。在下面的例子里remark列不会显示。函数
#coding=utf8 from django.contrib import admin class StudentModelAdmin(admin.Model): list_display = ['name','sex','remark'] def get_list_display(self, request): return ['name','sex']
动态性体如今能够根据每次请求的相关信息决定不一样的内容。具体来讲,在每一个选项的方法中都含有一个request参数,是HttpRequest类型的,表明了本次请求对象,你能够根据request包含一些请求相关信息和数据返回不一样的内容。经常使用见下表。工具
属性 | 类型 | 描述 |
path | string | 路径,不含主机和端口 |
method | string | 请求方法 |
GET/POST/REQUEST | dict | 请求数据 |
user | User/AnonymousUser | 当前登陆用户对应的User对象或匿名用户对象 |
list_display和get_list_display(self,request)返回是一个tuple或list,若是子类须要进行修改请使用list。每一个元素都是一个字符串,按优先级高低排列以下:
模型字段:在model定义的XxxField字段
函数:原型def get_filed_name(obj)
ModelAdmin方法:原型def get_filed_name(self,obj)
model方法:def get_filed_name(self)
最常使用的是1,2,3。第二/三种方法(它们的区别是一个写在ModelAdmin类外面,一个做为ModelAdmin成员函数)除了能够显示字符串以外,还能够显示html文本,好比一个连接、一张图片等,需设置allow_tags=True。下面是一个完整的例子,显示当前帐户的余额状态。
from django.contrib import admin class PayAccount(models.Model): customer = models.OneToOneField(Customer, verbose_name=u'客户') balance = models.FloatField(verbose_name=u'余额(元)', default=0) remark = models.CharField(max_length=200, verbose_name='备注', null=True, blank=True) def __unicode__(self): return self.customer.name class Meta: verbose_name = u'预缴帐户' verbose_name_plural = u'预缴帐户' #admin.py class PayAccountModelAdmin(CustomizeModelAdmin): def get_account_state(self, obj): if obj.balance < 0: return u'<span style="color:red;font-weight:bold">%s</span>' % (u"已欠费",) elif obj.balance <= 50: return u'<span style="color:orange;font-weight:bold">%s</span>' % (u"余额不足",) else: return u'<span style="color:green;font-weight:bold">%s</span>' % (u"正常",) get_account_state.short_description = u'帐户状态' get_account_state.allow_tags = True get_account_state.admin_order_field = 'balance' list_display = ['customer', 'balance', 'get_account_state', 'remark']
效果如图
def queryset(self,request)(django1.6如下)或def get_queryset(self,request)(django1.6+)
返回一个queryset对象,经常使用的作法是先调用父类的queryset方法获得默认结果集在进行过滤,固然仍是一次性访问数据库的。
在数据表格的右上角显示为一个过滤工具条,如图。每一个过滤值以一个连接形式展示。
list_filter是描述可过滤的列的集合,返回的是一个tuple或list。其中的每一个元素能够是如下的类型。
字段名称:这个字段能够是BooleanField, CharField, DateField, DateTimeField, IntegerField, ForeignKey 和ManyToManyField,不过若是可能值太多的话,仍是考虑用搜索的方法,否则过滤工具条会拖得很长。
一个继承自admin.SimpleListFilter的类,它主要有如下几个重要的属性和方法:
title:就是过滤条上“以”后面的文字。
def lookups(self,request,modeladmin):返回一个nX2的二维列表,每一个元素表明一个过滤值,前面是查询变量值,后面是显示在工具条的文字。
paramter_name:查询变量名
def queryset(self,request,queryset):返回结果集,在处理GET参数时已经复制给self.value()中了,所以这个函数的实现方式一般是 对self.value()进行判断,返回相应的结果集,不过注意一点的是self.value()是字符型,若是你的lookup是整数型的须要转化类型。
下面的这个例子实现了帐户余额状态过滤。
功能需求:状态分为三种:当余额大于50元时,为正常状态;当余额在0-50元(含0和50)时,为余额不足状态;当余额小于0时,为已欠费状态。由于数据存的是余额这个字段,状态过滤须要自定过滤器。
class AccountBalanceStateFilter(admin.SimpleListFilter): title = (u'余额状态') # Parameter for the filter that will be used in the URL query. parameter_name = 'balance_state' def lookups(self, request, model_admin): """ Returns a list of tuples. The first element in each tuple is the coded value for the option that will appear in the URL query. The second element is the human-readable name for the option that will appear in the right sidebar. """ return ( (0, u'正常'), (1, u'余额不足'), (2, u'已欠费'), ) def queryset(self, request, queryset): """ Returns the filtered queryset based on the value provided in the query string and retrievable via `self.value()`. """ if self.value(): if int(self.value()) == 0: return queryset.filter(balance__gt=50) if int(self.value()) == 1: return queryset.filter(balance__range=(0, 50)) if int(self.value()) == 2: return queryset.filter(balance__lt=0)
效果见上图。其中“已欠费”的连接GET字符串就含有:?balance_state=2。“所有”过滤值是admin自动添加的,它的链接就没有balance_state这个查询变量了。
另外,admin对于时间的过滤处理可使用上面的形式即在list_filter添加一个datetime类型的字段,还能够用date_hierarchy 选项控制,它将在表头显示一个“年-月-日”过滤器。
在ModelAdmin中与搜索有关的属性和方法是search_fields和get_search_results(request,queryset,search_term) 。
前者和显示和过滤同样,也是一个列名组成的list或tuple。每一个列必须是字符串或文本类型的,这个字段能够属于本model或者model的外键对象的,用'foreign_key__related_fieldname'形式表示。
在搜索类型方面,admin支持精确、模糊以及自定义搜索三种,默认是模糊搜索。还能够经过前缀符控制匹配的具体条件:^表示以此开始的字符;=表示精确匹配,@表示全文搜索。
具体参见官方Demo:
get_search_results(request,queryset,search_term)是定义当用户输入的文本内容应该返回的结果集。此方法Django1.6+有效。
排序可分为database层和django层。它们的区别是:
前者指的是数据库结果集返回的顺序,影响的是查询SOL的ORDER BY后面的内容,后者指的是传递给前台模板中queryset的顺序。
后者优先级大于前者,前者只有当调用ModelAdmin(Django内置,不是本身写的)queryset方法时候起做用。
前者只支持按数据已存在的列排序(由于要组成SQL),后者是结果集排序,因此支持自定义排序。(参见内置的sort函数)。
在admin中与排序有关有如下几个地方:
Model内部类Meta的ordering成员变量(database层)
ModelAdmin中ordering变量 (database层)
ModelAdmin中get_ordering(self, request)方法(database层)
ModelAdmin中queryset方法 (django层)
以上几项优先级按从低到高。database的排序配置和过滤、显示等同样,支持list或tuple,降序排序时在该列名字之间加“-”前缀。
在changelist页面来看,每一个可排序的列,一般是数据库的列的表头是带有连接的,点击后可按此列升降序排序。若是想让自定义的列也支持排序只要设置admin_order_field便可。好比在上述的例子中,想让帐户帐户状态按余额排序,只要添加如下如下代码便可。
get_account_state.admin_order_field = 'balance'
可是这种排序并非实时的,是新的HTTP请求,连接的地址能够看出是以"o"为查询变量的。格式相似于“o=1,-2”,即按list_display中第2列升序、第3列降序排列。