中秋快乐!新鲜出炉一篇DjangoAdmin使用合集,DjangoAdmin的功能比你想象的强大!
DjangoAdmin
DjangoAdmin本身就是一套大而全的系统,官方文档中介绍了很多配置方法,但仍然有大量的骚操作是文档中没有的,所以遇到特殊需求的时候,求助文档不一定有用。
在我看来 DjangoAdmin 虽然能快速生成一套管理后台,但如果要做大量特殊需求的定制,其成本不亚于用 Vue/React 重新开发一套,简单的使用成本不高,但深入定制的话需要对 DjangoAdmin 的工作流程比较熟悉,把源码啃熟了(有些 Python 源码没有类型注解是很难读懂的),才能在原有基础上雕花,有时候还存在着后续维护的问题。
不过还是瑕不掩瑜了,谁能拒绝配置了几行代码就可以用的管理后台呢?
而且还不需要你做出一套 RESTFul API 来实现前后端分离,直接一把梭,起飞~
一些参考资料
- Django Admin 后台自定制技巧:https://www.cnblogs.com/LyShark/p/12119539.html
- DjangoAdmin-字段自动补全(django_admin_autocomplete_all 库)使用与坑:https://django-admin-autocomplete-all.readthedocs.io/en/latest/readme.html
- DjangoAdmin添加自定义Widget:http://garmoncheg.blogspot.com/2014/07/django-adding-custom-widget-to-django.html
- How to Turn Django Admin Into a Lightweight Dashboard:https://hakibenita.com/how-to-turn-django-admin-into-a-lightweight-dashboard
界面主题
GitHub 上有很多 DjangoAdmin 的替换主题,所以不要抱怨 DjangoAdmin 的界面丑啦,好看的主题很多!
我最先使用的是 adminx,但这个侵入性太强了,需要对 admin 的配置代码做大量修改,实在是不划算,可能官方也意识到这个问题,后续应该是停更了。
到了 Django 2.x 时代后面,admin 的界面主题多了起来,有个国产的 SimpleUI 很不错,基于 Vue + ElementUI 实现的,star很多,算是比较成熟的一类,我愿称之为国产之光。
其他的我也大多有测试,但用起来总有一些兼容的问题,所以目前还是比较推荐国产之光。
SimpleUI
已经在多个产品中使用,使用 vue+elementUI(非单页应用),支持多标签页
一些相关的参考资料
- Django Admin SimpleUI 自定义列:https://simpleui.72wo.com/topic/1266
django-jazzmin
地址:https://github.com/farridav/django-jazzmin
这个是偶然发现的,对于看腻了 ElementUI 的人来说,会有眼前一亮的感觉
使用 Bootstrap+AdminLTE 重写,效果还不错
(就是偶尔会莫名卡死
而且细节方面做得不如 SimpleUI,比如搜索框没有 placeholder 的提示之类的。
定制案例
本文只记录特殊需求的实现,对于 DjangoAdmin 的常规配置就不复制粘贴了,网上随便一搜都有很多。
我之前已经写过不少 DjangoAdmin 的定制案例文章了,最近也做了不少定制,不过我不想写新文章来单独记录某个需求的实现过程了,直接在本文里记录,同时保持本文更新~
- 给Django Admin添加验证码和多次登录尝试限制
- Django中间件之实现Admin后台IP白名单
- 给Django的Admin添加自定义Action 并移除需要选择对象的限制
- 告别单调,Django后台主页改造 - 使用AdminLTE组件
添加自定义列
本案例基于 SimpleUI
效果图
实现过程
这里使用的是 ElementUI 的 Tag 组件,文档:https://element.eleme.cn/#/zh-CN/component/tag
前面提到过 SimpleUI 不是单页应用,是直接在网页上使用 vue 和 elementUI,并没有webpack环境
所以要加入 elementUI 的组件不能直接简单的
<el-tag type="success">标签</el-tag>
而是要用 webpack 生成出来的
<div class="el-tag el-tag--success el-tag--light">标签</div>
ok,开始上Python代码
假设有个 model 叫 Invoice
,中文名发票,定义如下
class Invoice(models.Model):
invoice_type = models.CharField('发票类型')
在需要自定义的 ModelAdmin 中,增加一个方法
# 发票类型颜色
@admin.display(description='发票类别')
def invoice_type_tag(self, obj: Invoice):
def el_tag(color_type, content):
"""
生成 ElementUI 的 tag 组件
:param color_type: success, info, warning, danger
:param content:
:return:
"""
from django.utils.safestring import mark_safe
type_class = '' if len(color_type) == 0 else f'el-tag--{color_type}'
return mark_safe(f'<div class="el-tag el-tag--small {type_class} el-tag--light">{content}</div>')
if obj.invoice_type.startswith('普通'):
return el_tag('', obj.invoice_type)
if obj.invoice_type.startswith('专用'):
return el_tag('danger', obj.invoice_type)
if obj.invoice_type.startswith('电子专票'):
return el_tag('info', obj.invoice_type)
if obj.invoice_type.startswith('电子普票'):
return el_tag('warning', obj.invoice_type)
然后把这个 invoice_type_tag
加到 list_display
中即可
PS:这里的 @admin.display()
装饰器是Django3.2版本之后新增的,很方便,相当于以前的
invoice_type_tag.short_description = '发票类别'
PS:注意HTML代码需要用 mark_safe
方法包装起来,才能正常渲染,不然会被转义!
显示进度条
效果图
实现过程
原理同上面的添加自定义列
代码如下
# 进度条
@admin.display(description='进度条')
def progress_bar(self, obj):
html = f'''
<div role="progressbar" aria-valuenow="{obj.progress}" aria-valuemin="0" aria-valuemax="100"
class="el-progress el-progress--line is-light el-progress--text-inside">
<div class="el-progress-bar">
<div class="el-progress-bar__outer" style="height: 22px;">
<div class="el-progress-bar__inner" style="width: {obj.progress}%;">
<div class="el-progress-bar__innerText">{obj.progress}%</div>
</div>
</div>
</div>
</div>
'''
from django.utils.safestring import mark_safe
return mark_safe(html)
页面上显示合计数额
效果图
实现过程
这个功能比较麻烦,因为需要魔改 template
首先我们要知道,这个列表对应的是哪个 template,在 admin 包的 templates 目录下面的找了半天,最终发现这个页面是 change_list
,而且因为页面比较复杂,被分成了好几部分
我们只需要修改 change_list.html
这个文件就行了。
admin.py
OK,模板代码先不管,我们来写Python代码计算总金额。
要实现将数据放在 context
里传给 template,得重写个 ChangeList
对象
from django.db.models import Sum
from django.contrib.admin.views.main import ChangeList
class InvoiceChangeList(ChangeList):
def get_results(self, request):
super(InvoiceChangeList, self).get_results(request)
totals = self.result_list.aggregate(Sum('amount'))
self.total_amount = totals['amount__sum']
使用 Sum
这个聚合方法,计算总金额。
通过Python语言的动态特性,加 total_amount
这个属性添加到 ChangeList
对象中
这样在 template 里就能通过 {{ cl.total_amount }}
的方式拿到这个属性。
然后改一下 ModelAdmin :
class InvoiceAdmin(ImportExportModelAdmin):
# 如果你改了 template 的名称,这里可以对应修改,否则默认即可
change_list_template = 'change_list.html'
# 添加这个代码
def get_changelist(self, request, **kwargs):
return InvoiceChangeList
后端部分搞定了,接下来是前端的模板部分。
template
为了在页面上添加新元素,我们来修改 change_list.html
文件。
注意,不要直接复制这个文件来修改!原因是你修改完的 template 会覆盖其他组件,这样以后换 admin 主题,或者使用 import-export 这类会修改 admin 页面的插件时无法生效,也就是所谓的兼容问题。
Django也想到了这种情况,这些 template 都是组件化的,我们写一个扩展 template 就可以了。
在项目的 templates/admin
目录下新建 change_list.html
文件,代码如下
{% extends "admin/import_export/change_list.html" %}
{% block result_list %}
{{ block.super }}
<div style="text-align: right; margin: 20px 5px; font-size: 20px;">
总金额:{{ cl.total_amount }} 元
</div>
{% endblock %}
注意:如果用了 django-import-export 插件,则要根据使用到的功能来添加 object-tools-items
block。
比如你的 ModelAdmin 继承自 ImportExportModelAdmin
,那我们转到源码,可以看到它重写了 template
class ImportExportMixin(ImportMixin, ExportMixin):
"""
Import and export mixin.
"""
#: template for change_list view
change_list_template = 'admin/import_export/change_list_import_export.html'
class ImportExportModelAdmin(ImportExportMixin, admin.ModelAdmin):
"""
Subclass of ModelAdmin with import/export functionality.
"""
然后再看看 admin/import_export/change_list_import_export.html
这个文件
{% extends "admin/import_export/change_list.html" %}
{% block object-tools-items %}
{% include "admin/import_export/change_list_import_item.html" %}
{% include "admin/import_export/change_list_export_item.html" %}
{{ block.super }}
{% endblock %}
可以看到它在 object-tools-items
中添加了俩组件,把这一块 block
的代码复制到我们的 change_list.html
中即可。
参考资料
扩展工具
这部分记录我在逛GitHub时发现的比较有意思的扩展库,记录一下
Django AdminPlus
地址:https://github.com/jsocol/django-adminplus
可以方便的给admin增加新页面
django-adminactions
地址:https://github.com/saxix/django-adminactions
可以给admin添加一系列的actions
- Export as CSV
- Export as Excel
- Export as fixture
- Export delete tree
- Mass update records
- Graph queryset
- Merge records
- Find Duplicates
中秋快乐!新鲜出炉一篇DjangoAdmin使用合集,DjangoAdmin的功能比你想象的强大!的更多相关文章
- 23套新鲜出炉的网站和手机界面 PSD 素材
Web 用户界面,移动用户界面和线框套件对设计师很有用,因为这些套件让他们使用快速和有效的方式复制用户界面.这些类型的工具包提供了一个基本的用户界面元素,用于它们需要制作的网站或软件模型. 在这篇文章 ...
- 22套新鲜出炉的 Web & Mobile PSD 用户界面素材
在这篇文章中,我们展示的是自由和清新的 UI 设计素材套件.这些线框图和 UI 设计工具包让设计师在设计用户界面原型的时候能够非常便利. Web 用户界面,移动用户界面和线框套件对设计师很有用,因为这 ...
- 新鲜出炉的30个精美的 jQuery & CSS3 效果【附演示和教程】
新鲜出炉的30个精美的 jQuery & CSS3 效果[附演示和教程] 作为最流行的 JavaScript 开发框架,jQuery 在现在的 Web 开发项目中扮演着重要角色,它简化了 ...
- 15个新鲜出炉的 Photoshop 文本效果教程
文本效果可能是 Photoshop 图形设计中最常用和最通用的技术之一.最重要的是你可以使用任何效果,风格或纹理来产生有趣的排版,越多人尝试过它并制作了一些精彩的教程.所以这篇文章旨在为您提供全面的 ...
- 微信小程序开发视频教程新鲜出炉
微信小程序开发公测了,可是对于新手来说,不同的框架不同的开发机制,如何快速适应呢?微信小程序开发视频教程新鲜出炉了,从零开始一步一步搭建微信小程序,每个章节都会涉及到不同的知识点,等教程学习完你不但掌 ...
- 刚写完的商城erp + 这个商城前台,新鲜出炉。自己1个人写, 包括php框架和前端html页面.
刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面. 刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面.
- 20个新鲜出炉的网站模板【HTML & PSD】
这里给大家分享20 个新鲜出炉的免费网站模板.这些设计元素将成为你下一个项目的重要素材,可以帮你节省很多的时间.与往常一样,我们经常漫游网络,寻找最好的资源, HTML.CSS 和 PSD 等等,记得 ...
- 分享25个新鲜出炉的 Photoshop 高级教程
网络上众多优秀的 Photoshop 实例教程是提高 Photoshop 技能的最佳学习途径.今天,我向大家分享25个新鲜出炉的 Photoshop 高级教程,提高你的设计技巧,制作时尚的图片效果.这 ...
- PS教程:20个新鲜出炉的 Photoshop 中级教程
Photoshop 实例教程是提高 Photoshop 技能的最佳学习途径.今天,我向大家分享最新20个 Photoshop 进阶教程,提高你的图片处理技巧,制作时尚的效果.这些教程可以帮助把你的想法 ...
随机推荐
- 深入浅出理解SVM支持向量机算法
支持向量机是Vapnik等人于1995年首先提出的,它是基于VC维理论和结构风险最小化原则的学习机器.它在解决小样本.非线性和高维模式识别问题中表现出许多特有的优势,并在一定程度上克服了" ...
- CentOS6安装使用ntp同步时间
[root@server yum.repos.d]# yum install ntp已加载插件:fastestmirror, priorities, refresh-packagekit, secur ...
- vivado没用上的寄存器变量
vivado中定义了但没用上的寄存器变量,在综合时会被移除,即没有综合出来.(如下cnt,虽然在y的过程块中用了cnt作为判断条件,但实际上cnt用了跟没用效果一样,所以综合时cnt_reg就被放弃了 ...
- linux系统中Nginx+FFmPeg+vlc实现网页视频播放配置过程
linux系统中Nginx+FFmPeg实现网页监控视频播放配置过程 1.安装好的nginx上添加模块nginx-http-fiv-module-master 此模块是rtmp模块的升级版,有它所有的 ...
- LevelSequence源码分析
前言 这篇文章主要讲的是Unreal LevelSequence RunTime的部分.即在游戏中运行Level Sequence的源码解析.(而且抛去Replicated 的Sequence,一般S ...
- JS 字符串转 GBK 编码超精简实现
前言 JS 中 GBK 编码转字符串是非常简单的,直接调用 TextDecoder 即可: const gbkBuf = new Uint8Array([196, 227, 186, 195, 49, ...
- 6.13 NOI 模拟
\(T1\ first\) \(bitset\)字符串匹配 \(yyds\) \(O(\frac{n^2}{w})\)就是正解! #include<bits/stdc++.h> #defi ...
- LuoguP5024 保卫王国(动态DP,LCT)
最小权覆盖集 = 全集 - 最大权独立集 强制取点.不取点可以使用把权值改成正无穷或负无穷实现 接下来就是经典的"动态最大权独立集"了 O(nlogn). 这不是我说的,是immo ...
- 深入理解Spring注解机制(一):注解的搜索与处理机制
前言 众所周知,spring 从 2.5 版本以后开始支持使用注解代替繁琐的 xml 配置,到了 springboot 更是全面拥抱了注解式配置.平时在使用的时候,点开一些常见的等注解,会发现往往在一 ...
- 彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-项目入口与路由EP01
书接上回,我们已经安装好Iris框架,并且构建好了Iris项目,同时配置了fresh自动监控项目的实时编译,万事俱备,只欠东风,彩虹女神蓄势待发.现在我们来看看Iris的基础功能,如何编写项目入口文件 ...