文档章节

django admin应用开发(2) 之 查看、过滤、搜索和排序

Kinegratii
 Kinegratii
发布于 2014/04/09 11:26
字数 2334
阅读 2343
收藏 15

django

 

第二节 查看、过滤、搜索和排序

2.1 ModelAdmin能做什么

ModelAdmin是admin应用中最常用的一个类,最终效果都将在这个类中体现出来。总的来说,这个类可以完成以下功能:

逻辑实现

单个对象(object)的操作:创建(add)、修改(change)、删除(delete)

结果集(queryset)的操作:查看(display)、搜索(search)、过滤(filter)、分页(paginator)、排序(sort)

权限控制:增删改查、自定义权限

界面布局

每个modelAdmin有四个页面,添加页面(add)、修改页面(change)、列表页面(changelist)、历史页面(history),每个页面含有自己特定的区域,称之为block。使用ModelAdmin自定义各个block的内容和位置。

2.2 ModelAdmin基本准则

MVT模式

admin应用和普通Django一样,也有自己的urls模块、views模块、template前台模板,记住它们的规则是非常必要的。urls-views-template对应关系在定义在django.contrib.admin.options.ModelAdmin的get_urls方法中。

    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 

ModelAdmin和Model

使用admin.site.register方法将ModelAdmin和Model关联起来,每个model只能拥有一个ModelAdmin与之关联,关联之后在ModelAdmin中可以使用self.model访问该model,ModelAmin方法的obj参数也是指的这个model。Model可以是一个代理模型类,使用方法参见这里proxy model

选项静态和动态配置

 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对象或匿名用户对象

 

 

2.3 数据查看

列显示

list_display和get_list_display(self,request)返回是一个tuple或list,如果子类需要进行修改请使用list。每个元素都是一个字符串,按优先级高低排列如下:

  1. 模型字段:在model定义的XxxField字段

  2. 函数:原型def get_filed_name(obj)

  3. ModelAdmin方法:原型def get_filed_name(self,obj)

  4. 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方法得到默认结果集在进行过滤,当然还是一次性访问数据库的。

2.4 数据过滤

在数据表格的右上角显示为一个过滤工具条,如图。每个过滤值以一个链接形式展现。

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 选项控制,它将在表头显示一个“年-月-日”过滤器。

2.5 搜索

 

在ModelAdmin中与搜索有关的属性和方法是search_fields和get_search_results(request,queryset,search_term) 。

基本搜索

前者和显示和过滤一样,也是一个列名组成的list或tuple。每个列必须是字符串或文本类型的,这个字段可以属于本model或者model的外键对象的,用'foreign_key__related_fieldname'形式表示。

在搜索类型方面,admin支持精确、模糊以及自定义搜索三种,默认是模糊搜索。还可以通过前缀符控制匹配的具体条件:^表示以此开始的字符;=表示精确匹配,@表示全文搜索。

具体参见官方Demo:

https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields

自定义搜索

get_search_results(request,queryset,search_term)是定义当用户输入的文本内容应该返回的结果集。此方法Django1.6+有效。

2.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列降序排列。

 

 

© 著作权归作者所有

Kinegratii

Kinegratii

粉丝 26
博文 11
码字总数 11517
作品 2
福州
后端工程师
私信 提问
django开发博客(1) 入门

现在正式开始博客开发 1、安装django1.4 如果你使用的是fedoraDVD版,安装时选择了web开发组建,这一步可以省略,因为它自带django环境 django下载地址 https://www.djangoproject.com/down...

蛀虫
2015/08/29
106
0
django admin查看、过滤和搜索

1 ModelAdmin能做什么 ModelAdmin是admin应用中最常用的一个类,最终效果都将在这个类中体现出来。总的来说,这个类可以完成以下功能: 逻辑实现 单个对象(object)的操作:创建(add)、修...

flyking
2014/04/09
9.5K
1
你应该使用 Django admin 的 9 个理由

本文源自 Reddit 上对我最近的一个帖子的评论: “问题是,我问到的每个人都持反对意见,他们认为 admin 只限于超级用户,很不灵活并且是难以定制。” —来自 Reddit 的 andybak 我现在要澄清...

有来有趣
2015/12/10
11.7K
24
django实例:创建你的第一个应用投票系统(3)后台管理

Django的管理面板默认是不开启的,所以我们需要进行一些设置工作 1、在INSTALLED_APPS里面把 django.contrib.admin 前面的注释去掉 2、运行 python manage.py syncdb ,建立和管理有关的表 3、...

DjangoChina
2013/06/01
460
3
【译】自己动手写Django app,第二部分【完】

原文地址:https://docs.djangoproject.com/en/1.4/intro/tutorial02/ 这个教程从教程一留下的东西开始的。我们继续网络调查应用程序同时我们将会关注Django的自动生成的管理站点。 (哲学:...

davidxp
2013/02/22
6.6K
13

没有更多内容

加载失败,请刷新页面

加载更多

医疗在线客服咨询系统有哪些特点?

随着中国互联网网站的的快速发展,至今医疗行业已经拥有了独立的的运营网站,其中最具特色的便属于医疗在线客服咨询系统,医疗在线客服咨询系统为每个访问网站的患者提供即时的网络在线客服服...

唯喏
42分钟前
9
0
skywalking(容器部署)

skywalking(容器部署) 标签(空格分隔): APM [toc] 1. Elasticsearch SkywalkingElasticsearch 5.X(部分功能报错、拓扑图不显示) Skywalking需要Elasticsearch 6.X docker network create......

JUKE
48分钟前
7
0
解决Unable to find a single main class from the following candidates [xxx,xxx]

一、问题描述 1.1 开发环境配置 pom.xml <plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><!--一定要对上springboot版本号,因......

TeddyIH
49分钟前
7
0
玩转Spring Boot 注册Servlet、Filter、Listener

玩转Spring Boot 注册Servlet、Filter、Listener JAVA架构师Ya七月 2019-08-23 玩转Spring Boot 注册Servlet、Filter、Listener 在Servlet 3.0之前我们都是使用web.xml进行配置,需要增加Ser...

Java架构师ya七
51分钟前
4
0
Dubbo服务限制大数据传输抛Data length too large: 13055248, max payload: 8388608解决方案

当dubbo服务提供者向消费层传输大数据容量数据时,会受到Dubbo的限制,报类似如下异常: 2019-08-23 11:04:31.711 [ DubboServerHandler-XX.XX.XX.XXX:20880-thread-87] - [ ERROR ] [com.al...

huangkejie
52分钟前
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部