你应该使用 Django admin 的 9 个理由

“问题是,我问到的每个人都持反对意见,他们认为 admin 只限于超级用户,很不灵活并且是难以定制。”
—来自 Reddit 的 andybak

我现在要澄清这个误解。Django 的 admin 绝对是软件中的亮点,可以有效的加速你的开发。

这里有一些我能想到的很有用的 Django 的 admin 模块的窍门。

(对于 Django admin 不太熟悉的人,先简单解释几个名词)

Changeform 是可以编辑对象的页面。

Changelist 页面可以列出指定类型的对象。你可以指定过滤对象的条件及对对象的操作。点击 changelist 里的对象一般会跳转到对象的 changeform 页面。

为了让这些敲门更具可操作性,我们使用了与真实问题几乎一致的场景。假设我们有一个简单的网站,访客可以上传可爱的动物图片并进行评论。这是不是很流行呢?

Tip 1:Django admin 后台不限于用 Django 开发的网站

虽然 Django admin 管理界面可以非常友好的用在 Django 项目的其它部分,它同样可以很容易用于其它像传统的数据库或具有一个可怕的的管理界面的网站。而且这也是评估 Django 是否会满足您的需求的最佳途径。

你需要做的仅是:

  1. 在你的 Django 项目中建立一个新的应用,并确保你已经连接好传统数据库 ,通过 settings.py 文件中的 DATABASES 的设置。
  2. 将你的数据表定义为 Django 的模型。正如它的名字所表述的,manage.py inspectdb 是一个非常有用的命令:检测现有的数据库,并打印出自动生成的 Django 模型。
  3. 创建 admin.py 文件,并放在那里,唉,管理相关的。稍后将详细说明这个。

说到我们的动物“的网站,是由进屎的脑袋写出来的,所以管理界面看起来像……你知道的,不是很好。为了解决这个问题,我们通过几个 Django 模型重构了数据库结构,实现一个简单的管理界面:

 

Tip #2: 按你喜欢的方式筛选你的数据

很多人使用 Django admin 后台对指定字段进行筛选。要知道,把一个字段名放到 list_filter 列表里就可以了。同时它也非常容易地创建一个自定义过滤器!

假如最终你决定要推广所有有 100+ 的帖子的作者。但是,我们如何区分它们?让我们创建一个过滤器,并把它添加到我们的变更列表。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class ProductiveAuthorsFilter(admin.SimpleListFilter):
    parameter_name = 'is_productive'
    title = 'Productive author'
    YES, NO = 1, 0
 
    # Number of comments for an author to be considered a productive one
    THRESHOLD = 100
 
    def lookups(self, request, model_admin):
        return (
            (self.YES, 'yes'),
            (self.NO, 'no'),
        )
 
    def queryset(self, request, queryset):
        qs = queryset.annotate(Count('comments'))
 
        # Note the syntax. This way we avoid touching the queryset if our
        # filter is not used at all.
        if self.value() == self.YES:
            return qs.filter(comments__count__gte=self.THRESHOLD)
        if self.value() == self.NO:
            return qs.filter(comments__count__lt=self.THRESHOLD)
 
        return queryset
 
class PictureAdmin(admin.ModelAdmin):
    list_filters = [..., ProductiveAuthorsFilter]

现在,我们可以很容易地选出我们的核心作者。那么我们如何开始向他们推广呢?让我们进入下一部分。

Tip #3:添加动作(操作函数)到 ‘actions’

这可是内容管理者的天赐之物。还记得在每个模型的列表顶部的“动作”工具栏不?我们是不是非常方便的先选择一些图片,然后只需单击一下就“推广”给作者了?现在让我们来实现它:

 
 
1
2
3
4
5
6
7
class PictureAdmin(admin.ModelAdmin):
    actions = ['promote', ]
 
    def promote(self, request, queryset):
        queryset.update(is_promoted=True)
        self.message_user(request, 'The posts are promoted')
    promote.short_description = 'Promote the pictures'

就是这样!不用再一个挨一个的打开每个表单!另外,它很容易进一步增加我们的动作,例如,添加一个过渡表单。关于这点,Django 文档 有段非常棒的讲解

Tip #4: 搜索你需要的所有字段

好吧,过滤器是很酷,但让我们关注了一下就搜索工具。在几乎所有的安装我见过的搜索框是用来在一个模型中的字段搜索。但是,当你意识到它可以处理关系的 Django 搜索真正的亮点。因此,假设我们希望它在图片“的标题,作者姓名和注释”文本进行搜索。我们如何做到这一点?

 
 
1
2
class PictureAdmin(admin.ModelAdmin):
    search_fields = ('title', 'author__name', 'comments__text', )

如果你的数据库是够大,不要忘记添加一些全文索引来增加搜索速度。

Tip #5: “在站点查看”的简单实现

在站点查看一个对象的界面是非常普及的需求,默认情况下,你必须打开该对象的表单,然后点击按钮“在站点查看”。以下代码展示如何使此过程更容易一些:

 
 
1
2
3
4
5
6
7
8
class PictureAdmin(admin.ModelAdmin):
    list_fields = [..., 'object_link']
 
    def object_link(self, item):
        url = item.get_absolute_url()
        return u'<a href={url}>open</a>'.format(url=url)
    object_link.short_description = 'View on site'
    object_link.allow_tags = True

这段代码给列表中每个对象都添加了“在站点查看”的链接。在此,我们假定你的模型(Model)已经实现了get_absolute_url()方法。如果还没有 – 那现在就去实现 ,这将为你节省很多时间。你也可能会想将这个片段转移到一个 mixin,或公用的 admin 基类。

Tip #6: 在列表页就地编辑字段

假设我们需要给评论加一个编辑的备注。很自然,我们希望不需要对每条评论都去打开评论的changeform。要做到这点,我们可以稍微修改一下ModelAdmin:

 
 
1
2
3
class CommentAdmin(admin.ModelAdmin):
    list_display_fields = ('picture', 'author', 'editors_note', )
    list_editable = ('editors_note', )

这样就搞定了,现在打开评论列表,可以按照需要进行过滤,还可以在评论上即时添加备注。

Tip #7: 根据需要自定义 total 字段

每个 changelist 最下方都有一行列出总数(total)。假设我们需要把猫和狗的图片数量区分开来。这个功能需要的代码稍微多一些:我们需要重载 changelist 和 html 模板(更多内容参考模板重载)。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django.contrib.admin.views.main import ChangeList
 
class PicturesChangeList(admin.ChangeList):
    def get_results(self, request):
        super(PicturesChangeList, self).get_results(request)
        totals = self.result_list.aggregate(
            dogs_count=Sum(Case(When(animal_kind=Picture.DOG, then=1),
                           output_field=IntegerField())),
            cats_count=Sum(Case(When(animal_kind=Picture.CAT, then=1),
                           output_field=IntegerField())))
        self.totals = totals
 
class PictureAdmin(admin.ModelAdmin):
    def get_changelist(self, request):
        return PicturesChangeList

模板的内容:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
{% extends 'admin/change_list.html' %}
{% block result_list %}
    {{ block.super }}
    <p>
        There are
        <strong>
            {{ cl.totals.dogs_count|default:'none' }} dogs and
            {{ cl.totals.cats_count|default:'none' }} cats
        </strong>
        on this page.
    </p>
{% endblock %}

Tip #8: 对某些用户只读的 admin 界面

啥意思?假设你的祖母打算瞅一眼这些可爱的图片,她站在你背后,觉得 Django 的 admin 界面挺有意思。不过你能肯定,她要是使用 admin 界面,恐怕一个按钮的点击就能毁掉整个网站。那么,我们加上 grandma-proof™,这样就支持只读的 admin 界面(就是某人说的“数据浏览”):

 

现在你可以安全的把修改图片的权限放开给你的祖母,这样她就能浏览图片列表。要注意这个方案肯定不能适用于所有使用场景,你还需要处理更多的情况

Tip #9: 为每个对象自定义 action

有时候你需要在单个对象上执行特定的 action。‘actions’工具当然可以完成这个任务,不过过程会显得很麻烦:点击对象、选择 action、再点击一个按钮……肯定有更便捷的方式,对吧?让我们想办法只点击一次就全部搞定。

这次我们要实现老祖母的另一个宏达的想法。她希望能给某些编辑发 email,告诉他们她喜欢的所有图片。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class PictureAdmin(admin.ModelAdmin):
    list_fields = (..., 'mail_link', )
 
    def mail_link(self, obj):
        dest = reverse('admin:myapp_pictures_mail_author',
                       kwargs={'pk': obj.pk})
        return '<a href="{url}">{title}</a>'.format(url=dest, title='send mail')
    mail_link.short_description = 'Show some love'
    mail_link.allow_tags = True
 
    def get_urls(self):
        urls = [
            url('^(?P<pk>\d+)/sendaletter/?$',
                self.admin_site.admin_view(self.mail_view),
                name='myapp_pictures_mail_author'),
        ]
        return urls + super(PictureAdmin, self).get_urls()
 
    def mail_view(self, request, *args, **kwargs):
        obj = get_object_or_404(Picture, pk=kwargs['pk'])
        send_mail('Feel the granny\'s love', 'Hey, she loves your pet!',
                  'granny@yoursite.com', [obj.author.email])
        self.message_user(request, 'The letter is on its way')
        return redirect(reverse('admin:myapp_picture_changelist'))

但愿她现在能够满意。现在每个对象字段加上了一个链接,让她点一下就可以发送邮件。

Bonus Tip: 只需为 admin 添加一行代码来减少查询量

Django admin (Django 也是如此) 最常用也是最有用的技巧是 select_related。呃,你已经都知道了?不就是把对象的名字传给 ModelAdmin 的 list_select_related 属性来实现相关对象的预加载嘛。但是,你知道你并没有描述全部的相关对象吗?只需要设置成 True,Django 就可以自动预加载外部对象:

 
 
1
2
class PictureAdmin(admin.ModelAdmin):
    list_select_related = True

本文到此就差不多结束了,希望你能觉得有意思。别忘了在评论里分享你的看法,告诉我们对你有帮助的技巧。

你应该使用 Django admin 的 9 个理由(转)的更多相关文章

  1. Django admin美化插件suit应用[原创]

    前言 由于比较懒,自己弄了一个用户验证,没有自己写后台,用了django自带的user认证,并通过admin直接进行管理,但默认的admin并不漂亮,于是使用了这个django-suit插件,效果对比 ...

  2. Django admin 权威指南(一)

    版本: Django 1.10 此部分由官方文档<6.5.1 The Django admin site>翻译而来. 6.5.1.1 概览 默认情况下,使用startproject的时候, ...

  3. Django admin 显示图片

    我有一个表用来储存轮播图片,有一个 `picture` 字段储存的是图片的url,图片的 url 通过上传文件到 cdn 获得.目前这个表的编辑是通过自定义一个 `ModelForm`,然后重写 Dj ...

  4. [系统开发] Django Admin上传图片简单校验

    我的 models里有个ImageField字段,用来保存用户头像,希望通过Django Admin上传时校验头像大小,如果太大就报错,并且不保存. 网上有不少方法,有的通过第三方软件实现,有的通过自 ...

  5. SQLAlchemy连接数据库并在django admin显示

    SQLAlchemy 0.7     postgersql  9.0 SQLAlchemy连接数据库有两种方法,一种是classic,一种是modern 1,modern方法 from sqlalch ...

  6. Django admin site(一)ModelAdmin Options

    Admin管理界面是django的杀手级应用.它读取你模式中的元数据,然后提供给你一个强大而且可以使用的界面,网站管理者可以用它立即向网站中添加内容. 要使用admin,可以按照下面的步骤: 将'dj ...

  7. Django Admin 简单部署上线

    前言 打算为公司弄一个管理公用密码的平台,由于比较懒,就选择使用Django admin,默认的admin并不漂亮,于是我使用了这个django-suit插件来美化 如图: 是不是比原来的漂亮多了. ...

  8. Django admin究竟要怎么写才优雅

    比如在Django admin 注册models时,会用到. 对于APP里自带的models,可以使用这种方式注册. from django.contrib import admin # Regist ...

  9. django admin.py settings 操作

    dango, 怎么说呢,什么东西都内置了,什么东西都是自己的东西.用过flask, cherrypy, web.py, pyramid 等等python 框架后,再选用dango 觉得,理念有很大的区 ...

随机推荐

  1. librec库

    固定初始化矩阵值 net.librec.math.structure -> class DenseMatrix -> void init()

  2. Windows2012启动自动帐户登陆

    Win+R 启动 输入regedit  运行注册表 找到[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogo ...

  3. erl_0021 erlang和java的内存模型比较(引用)

    原文  http://deepinmind.iteye.com/blog/2030390 我读到一篇相当相当有趣的关于Erlang VM内存管理策略的文章.它是Jesper Wilhelmsson写的 ...

  4. ZOJ3640Help Me Escape(师傅逃亡系列•一)(数学期望||概率DP)

    Background If thou doest well, shalt thou not be accepted? and if thou doest not well, sin lieth at ...

  5. Luogu 4724 三维凸包

    Luogu 4724 三维凸包 增量法,维护当前凸包,每次加入一个点 \(P\) ,视其为点光源,将可见面删去,新增由"晨昏线"(分割棱)与 \(P\) 构成的平面. 注意每个平面 ...

  6. elixir jenkins 集成构建方式配置

    备注:    主要问题是环境变量配置的问题,解决方法是使用软连接进行解决   1. 下载软件包 wget https://github.com/elixir-lang/elixir/releases/ ...

  7. JavaScript中的函数(一)

    javaScript中的函数实际上是对象,每一个函数都是Function类型的实例,和其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也就是一个指向函数对象的指针,也就是函数对象的一个 ...

  8. ‘close’ was not declared in this scope(转)

    ‘close’ was not declared in this scope 没有包含头文件 unistd.h 造成的. 加上' #include <unistd.h>

  9. 网站建设之高速WEB的实现

    1.此文目的 漂亮的色彩.绚丽的动画在输入网址后便能呈现在你的眼前.互联网无可否认已经融入了我们的生活. 我们可以山寨出iPhone却很难有属于自己独特的理念关于事物的思想和心脏. 互联网是现实.艺术 ...

  10. SPUtils

    public class SPUtils { /** * 保存在手机里的SP文件名 */ public static final String FILE_NAME = "my_sp" ...