2019独角兽企业重金招聘Python工程师标准>>>

自定制Admin

如果只是在admin中简单的展示及管理模型,那么在admin.py模块中使用admin.site.register将模型注册一下就好了:

from django.contrib import admin
from myproject.myapp.models import Authoradmin.site.register(Author)

ModelAdmin类是一个模型在admin页面里的展示方法,如果你对默认的admin页面满意,那么你完全不需要定义这个类,直接使用最原始的样子也行。通常,它们保存在app的admin.py文件里。下面是个简单的例子:

from django.contrib import admin
from myproject.myapp.models import Author# 创建一个ModelAdmin的子类
class AuthorAdmin(admin.ModelAdmin):pass# 注册的时候,将原模型和ModelAdmin耦合起来
admin.site.register(Author, AuthorAdmin)

注册装饰器

除了常用的admin.site.register(Author, AuthorAdmin)方式进行注册,还可以用装饰器的方式连接模型和ModelAdmin。如下所示:

from django.contrib import admin
from .models import Author@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):pass

这个装饰器可以接收一些模型类作为参数,以及一个可选的关键字参数site(如果你使用的不是默认的AdminSite),比如。

from django.contrib import admin
from .models import Author, Reader, Editor
from myproject.admin_site import custom_admin_site@admin.register(Author, Reader, Editor, site=custom_admin_site)
class PersonAdmin(admin.ModelAdmin):pass

注册位置

当你在INSTALLED_APPS设置中添加了django.contrib.admin后,Django将自动在每个应用中搜索admin模块并导入它。也就是说,通常我们在每个app下都有一个admin.py文件,将当前app和admin有关的内容写到内部的admin.py文件中就可以了,Django会自动搜索并应用它们。

ModelAdmin的属性

ModelAdmin非常灵活,它有许多内置属性,帮助我们自定义admin的界面和功能。所有的属性都定义在ModelAdmin的子类中,如下方式:

ModelAdmin.date_hierarchy

根据你指定的日期相关的字段,为页面创建一个时间导航栏,可通过日期过滤对象。例如:

from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):date_hierarchy = 'pub_date'

ModelAdmin.empty_value_display

指定空白显示的内容。如果你有些字段没有值(例如None,空字符串等等),默认情况下会显示破折号“###”。这个选项可以让你自定义显示什么,如下例就显示为“###empty###”

from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):empty_value_display = '###empty###'

某个函数设置空白值或者整个站点设置为空

from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):fields = ('name', 'title', 'view_birth_date')def view_birth_date(self, obj):return obj.birth_date# 注意下面这句view_birth_date.empty_value_display = '???'

如果某个字段的值为None或空字符串或空的可迭代对象,那么默认显示为短横杠“###”,你可以使用AdminSite.empty_value_display在全局改写这一行为:

from django.contrib import admin
admin.site.empty_value_display = '(None)'

或者使用ModelAdmin.empty_value_display只改变某个类的行为:

class PersonAdmin(admin.ModelAdmin):empty_value_display = 'unknown'

但如果你给这个方法添加一个boolean的属性并赋值为True,它将显示为on/off的图标,如下图:

from django.db import models
from django.contrib import admin
class Person(models.Model):first_name = models.CharField(max_length=50)birthday = models.DateField()def born_in_fifties(self):return self.birthday.strftime('%Y')[:3] == '195'# 关键在这里born_in_fifties.boolean = True
class PersonAdmin(admin.ModelAdmin):# 官方文档这里有错,将'name'改为'first_name' list_display = ('first_name', 'born_in_fifties')

ModelAdmin.exclude

不显示指定的某些字段。如下例有这么个模型:

from django.db import models
class Author(models.Model):name = models.CharField(max_length=100)title = models.CharField(max_length=3)birth_date = models.DateField(blank=True, null=True)
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):# 一定注意了,值是个元组!一个元素的时候,最后的逗号不能省略。exclude = ('birth_date',)

ModelAdmin.fields

按你希望的顺序,显示指定的字段。与exclude相对。但要注意与list_display区分。这里有个小技巧,你可以通过组合元组的方式,让某些字段在同一行内显示,例如下面的做法“url”和“title”将在一行内,而“content”则在下一行。

class FlatPageAdmin(admin.ModelAdmin):fields = (('url', 'title'), 'content')

ModelAdmin.form

默认情况下,admin系统会为你的模型动态的创建ModelForm,它用于创建你的添加/修改页面的表单。我们可以编写自定义的ModelForm,在"添加/修改"页面覆盖默认的表单行为。 注意:如果你的ModelForm和ModelAdmin同时定义了exclude选项,那么ModelAdmin中的具有优先权,如下例所示,"age"字段将被排除,但是“name”字段将被显示:

from django import forms
from django.contrib import admin
from myapp.models import Person
class PersonForm(forms.ModelForm):class Meta:model = Personexclude = ['name']
class PersonAdmin(admin.ModelAdmin):exclude = ['age']form = PersonForm

ModelAdmin.formfield_overrides

这个属性比较难以理解,通过一个列子来解释可能会更好一点。设想一下我们自己写了个RichTextEditorWidget(富文本控件),然后想用它来代替传统的文本域控件,用于输入大段文字。我们可以这么做:

from django.db import models
from django.contrib import admin
# 从对应的目录导入我们先前写好的widget和model
from myapp.widgets import RichTextEditorWidget
from myapp.models import MyModel
class MyModelAdmin(admin.ModelAdmin):formfield_overrides = {models.TextField: {'widget': RichTextEditorWidget},}

ModelAdmin.list_display

指定显示在修改页面上的字段。这是一个很常用也是最重要的技巧之一。例如

from django.db import models
from django.contrib import admin
from django.utils.html import format_html
class Person(models.Model):first_name = models.CharField(max_length=50)last_name = models.CharField(max_length=50)color_code = models.CharField(max_length=6)def colored_name(self):# 关键是这句!!!!!请自己调整缩进。return '<span style="color: #%s;">%s %s</span>'%(self.color_code,self.first_name,self.last_name,)
class PersonAdmin(admin.ModelAdmin):list_display = ('first_name', 'last_name', 'colored_name')

想要有个CSS效果,但Django把它当普通的字符串了。怎么办呢?用format_html()或者format_html_join()或者mark_safe()方法!

from django.db import models
from django.contrib import admin
# 需要先导入!
from django.utils.html import format_html
class Person(models.Model):first_name = models.CharField(max_length=50)last_name = models.CharField(max_length=50)color_code = models.CharField(max_length=6)def colored_name(self):# 这里还是重点,注意调用方式,‘%’变成‘{}’了!return format_html('<span style="color: #{};">{} {}</span>',self.color_code,self.first_name,self.last_name,)
class PersonAdmin(admin.ModelAdmin):list_display = ('first_name', 'last_name', 'colored_name')

通常情况下,在list_display列表里的元素如果不是数据库内的某个具体字段,是不能根据它进行排序的。但是如果给这个字段添加一个admin_order_field属性,并赋值一个具体的数据库内的字段,则可以按这个字段对原字段进行排序,如下所示:

from django.db import models
from django.contrib import admin
from django.utils.html import format_html
class Person(models.Model):first_name = models.CharField(max_length=50)color_code = models.CharField(max_length=6)def colored_first_name(self):return format_html('<span style="color: #{};">{}</span>',self.color_code,self.first_name,)# 就是这一句了!colored_first_name.admin_order_field = 'first_name'
class PersonAdmin(admin.ModelAdmin):list_display = ('first_name', 'colored_first_name')

ModelAdmin.list_filter

设置list_filter属性后,可以激活修改列表页面的右侧边栏,用于对列表元素进行过滤,如下图: list_filter必须是一个元组或列表,其元素是如下类型之一:

class PersonAdmin(admin.ModelAdmin):list_filter = ('is_staff', 'company')

ModelAdmin.list_max_show_all

设置一个数值,当列表元素总数小于这个值的时候,将显示一个“show all”链接,点击后就能看到一个展示了所有元素的页面。该值默认为200.

ModelAdmin.list_per_page

设置每页显示多少个元素。Django自动帮你分页。默认为100。

ModelAdmin.save_as

默认情况下,它的值为False。如果设置为True,那么右下角的“Save and add another”按钮将被替换成“Save as new”,意思也变成保存为一个新的对象

ModelAdmin.search_fields

设置这个属性,可以为admin的修改列表页面添加一个搜索框。

ModelAdmin.view_on_site

这个属性可以控制是否在admin页面显示“View site”的链接。这个链接主要用于跳转到你指定的URL页面。 属性的值可以是布尔值或某个调用。如果是True(默认值),对象的get_absolute_url()方法将被调用并生成rul。 如果你的模型有一个get_absolute_url()方法,但你不想显示“View site”链接,你只需要将view_on_site属性设置为False。

from django.contrib import admin
class PersonAdmin(admin.ModelAdmin):view_on_site = False

如果属性的值是一个调用,它将接收一个模型实例作为参数:

from django.contrib import admin
from django.urls import reverse
class PersonAdmin(admin.ModelAdmin):def view_on_site(self, obj):url = reverse('person###detail', kwargs={'slug': obj.slug})return 'https://example.com' + url

自定义Admin actions

下面以一个新闻应用的文章模型为例,介绍一个批量更新的自定义actions,它将选择的文章由“草稿”状态更新为“发布”状态:

首先是模型的代码:

from django.db import modelsSTATUS_CHOICES = (('d', 'Draft'),('p', 'Published'),('w', 'Withdrawn'),
)class Article(models.Model):title = models.CharField(max_length=100)body = models.TextField()status = models.CharField(max_length=1, choices=STATUS_CHOICES)def __str__(self):              # __unicode__ on Python 2return self.title

编写action

action必须携带三个参数: 当前的ModelAdmin 当前的HttpRequest对象(即request) 被选择的对象(即QuerySet) 在应用中的admin.py文件中写入:

def make_published(modeladmin, request, queryset):queryset.update(status='p')

但在多数情况下,你要自己遍历queryset的每个元素,并编写具体的操作。也就是:

for obj in queryset:do_something_with(obj)

还可以设置一个简单易懂的简短描述(可以使用中文),用于代替生硬的函数名:

def make_published(modeladmin, request, queryset):queryset.update(status='p')
# 注意缩进,下面这句不在函数体内。
make_published.short_description = "Mark selected stories as published"

将自定义action添加到对应的ModelAdmin中 关键是其中的actions = [make_published]这句。

from django.contrib import admin
from myapp.models import Articledef make_published(modeladmin, request, queryset):queryset.update(status='p')
make_published.short_description = "Mark selected stories as published"class ArticleAdmin(admin.ModelAdmin):list_display = ['title', 'status']ordering = ['title']actions = [make_published]admin.site.register(Article, ArticleAdmin)

将action定义为ModelAdmin的方法

class ArticleAdmin(admin.ModelAdmin):...actions = ['make_published']  # 请注意这里改成字符串引用了# 第一个参数变为selfdef make_published(self, request, queryset):queryset.update(status='p')make_published.short_description = "Mark selected stories as published"
#这其中,如果你能够预知在自定义的操作中可能产生的错误,请处理该错误,并通过django.contrib.admin.ModelAdmin.message_user()以友好的方式给予用户提示信息。
class ArticleAdmin(admin.ModelAdmin):...def make_published(self, request, queryset):rows_updated = queryset.update(status='p')if rows_updated == 1:message_bit = "1 story was"else:message_bit = "%s stories were" % rows_updatedself.message_user(request, "%s successfully marked as published." % message_bit)

跳转到中间页面

默认情况下,执行完actions后,浏览器会返回先前的修改列表页面。但有时候,一些复杂的action需要返回中间页面,例如内置的删除方法,在执行删除动作之前,会弹出一个删除确认页面。

要实现这个功能,只需要在action方法中返回一个HttpResponse(或它的子类)。 例如下面是一个利用Django内置的序列化函数将一个对象保存为json格式的范例:

from django.http import HttpResponse
from django.core import serializersdef export_as_json(modeladmin, request, queryset):response = HttpResponse(content_type="application/json")serializers.serialize("json", queryset, stream=response)return response

多数情况下,我们会使用HttpResponseRedirect跳转到一个中间页面,并在GET方法的url中携带别选择的对象作为参数传递过去,然后在这个新的视图中接收这个参数,并编写具体的更加复杂的业务逻辑,如下面的代码所示:

from django.contrib import admin
from django.contrib.contenttypes.models import ContentType
from django.http import HttpResponseRedirectdef export_selected_objects(modeladmin, request, queryset):# 获得被打钩的checkbox对应的对象selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)# 获取对应的模型ct = ContentType.objects.get_for_model(queryset.model)# 构造访问的url,使用GET方法,跳转到相应的页面return HttpResponseRedirect("/export/?ct=%s&ids=%s" % (ct.pk, ",".join(selected)))

编写可用于整个admin站点的action

前面创建的actions智能应用于绑定的模型。实际上有时候,我们还需要可以对admin站点内所有模型都有效的acitons。上面写的export_selected_objects函数可以是一个很好的例子。要实现这一功能,你需要使用内置的AdminSite.add_action方法:

AdminSite.add_action(action, name=None)[source]

from django.contrib import adminadmin.site.add_action(export_selected_objects)

禁用acitons

有时候,对于某些actions,我们想全局禁用或者局部禁用它。需要使用AdminSite.disable_action(name)方法。

禁用全站级别的acitons:

admin.site.disable_action('delete_selected')
# 全站禁用删除功能
admin.site.disable_action('delete_selected')# 这个老老实实的被禁了
class SomeModelAdmin(admin.ModelAdmin):actions = ['some_other_action']...# 这个声明:我还要用
class AnotherModelAdmin(admin.ModelAdmin):actions = ['delete_selected', 'a_third_action']...

在指定模型中禁用所有actions:设置ModelAdmin.actions为None。(这会连带全局actions一起禁用了。)

class MyModelAdmin(admin.ModelAdmin):actions = None

根据条件自动启用或禁用: 还可以根据条件自动选择性的启动或禁用某些acitons,你只需要改写ModelAdmin.get_actions()方法。

该方法将返回一个包含actions的字典。字典的键是aciton的名字(也就是前面的'delete_selected', 'a_third_action'之类),值是一个元组,包含(函数、名字、别名)

例如,允许用户名以“J”开头的用户批量删除对象,但其它用户不行:

class MyModelAdmin(admin.ModelAdmin):...def get_actions(self, request):actions = super(MyModelAdmin, self).get_actions(request)if request.user.username[0].upper() != 'J':if 'delete_selected' in actions:del actions['delete_selected']return actions

转载于:https://my.oschina.net/jiansin/blog/1844641

Django后台定制相关推荐

  1. Django后台admin的使用

    Django后台admin的使用 1.简述 2.创建数据库表 3.修改admin.py文件 4.启动服务,进入界面 5.自定义表显示内容: 6.自定义动作 1.简述 Django的admin可以提供一 ...

  2. Python | 7招教你识别一个网站是否是Django后台

    戳蓝字"CSDN云计算"关注我们哦! 作者 l 上海小胖 来源 l Python专栏(ID:xpchuiit) 转载请联系授权(微信ID:pythonzhuanlan) 目录: 1 ...

  3. python3 django html 中文乱码_解决django后台管理界面添加中文内容乱码问题

    在学习使用django做一个简单的个人博客项目,通过admin后台添加中文文章内容的时候,遇到中文内容显示乱码的问题. 排除了网上资料中的提到的几个问题: 1.数据上传默认采用的是unicode编码 ...

  4. 网页短信平台国际通道搭建|后台定制-移讯云短信系统

    网页短信平台国际通道搭建|后台定制-移讯云短信系统 这里先介绍下客户的定制需求,稍候放出开发构架和开发思路 我们根据市场需要,开发了一套可以接入国际通道的短信系统. 一:客户对短信平台系统开发的定制要 ...

  5. django后台搜索显示Related Field got invalid lookup: icontains

    项目场景: django后台搜索 问题描述 输入搜索后显示字段错误类型并报Related Field got invalid lookup: icontains的错误 原因分析: 根据百度查找原因是查 ...

  6. 如何在Django后台添加pagedown

    需求描述 某公司的项目需要接入大数据,但是项目人员要求只用sql查询.经过通宵达旦的搞了一段时间,终于小有成效.然后我们又做了个大数据开发平台网站,里面放了些开发文档.以为我们队python比较熟悉, ...

  7. DJANGO后台ADMIN下拉三级联动,纯JS,没有AJAX数据库回显,目前为止最简单的做法

    网上有很多的DJANGO下拉三级联动,但是都涉及到数据库回显数据操作,操作复杂,本例子是把下拉数据写在JS中,很简单,不需要修改后台太多文件,最下面是一个正常的HTML下拉三级联动文件,我们在这个文件 ...

  8. 国际网页短信后台定制源码搭建软件平台定制-移讯云短信系统

    国际网页短信后台定制源码搭建软件平台定制-移讯云短信系统 短信服务端号码通道分类功能 短信后开发按照要求有个功能是发送分流.就是当短信客户端提交过来的短信号码包含移动.联通.电信时,系统要实现不通类型 ...

  9. python 写出好看且实用的后台管理-django 后台管理美化

    django 后台管理美化 安装 django-simpleui pip install django-simpleui -i https://pypi.tuna.tsinghua.edu.cn/si ...

最新文章

  1. python笔记6 模块与包 程序开发规范 包 re sys time os模块
  2. parquet java_Apache Parquet Java API的文档?
  3. EOSRAM那么火,BANCOR协议白皮书了解一下?
  4. linux启动redis_Redis简介
  5. hdu 1251 统计难题(求前缀出现了多少次)
  6. Python的WSGI
  7. HikariCP 的Java数据库连接池介绍及配置
  8. SpringBoot+zk+dubbo架构实践(一):本地部署zookeeper
  9. Linux驱动开发流程
  10. switch芯片上的QoS,VLAN介绍
  11. 软件推荐┊最有效防止被聚生网管、P2P终结者等管理软件控制的小工具——ARP防火墙单机版...
  12. keil 结构体引用_详解keil采用C语言模块化编程时全局变量、结构体的定义、声明以及头文件包含的处理方法...
  13. eclipse的安装及最大子数组求和
  14. 万字拆解!追溯ChatGPT各项能力的起源
  15. java基础编程题及答案,三面蚂蚁金服(交叉面)定级阿里P6
  16. Uncaught SyntaxError: Unexpected identifier问题解决
  17. 【Kaggle竞赛】Kaggle竞赛了解
  18. 计算机网络——网络工程项目
  19. Ranklib部分源码分析
  20. 浏览器网站请求全解析

热门文章

  1. C/S架构程序多种类服务器之间实现单点登录(转)
  2. Cocos2d-x项目移植到WP8系列之二:开篇
  3. 【Java基础】集合
  4. 【中文】Joomla1.7扩展介绍之Kunena(强大的论坛)
  5. 一起谈.NET技术,也玩MVC3.0 Razor自定义视图引擎来修改默认的Views目录结构
  6. C# WinForm 技巧四:COMBOBOX搜索提示
  7. 【前端笔记】Vuex 是什么,为什么需要
  8. Linux内核源码树学习:Kconfig和Makefile
  9. 华东师范大学2019年高等代数考研试题
  10. Java HttpSession 详解