一、特点与解释
- Xadmin介绍 直接替换掉Django自带的admin系统,并提供了很多有用的东西;完全的可扩展的插件支持,基于Twitter Bootstrap的漂亮UI 本课程使用版本为:python3.7 Django2.2.3 xadmin2
- Xadmin特点
- 完全替代Django admin
- 支持基于Twitter Bootstrap的UI主题
- 支持可扩展的插件
- 更好的过滤器,日期范围,数量范围等
- 内置xls,csv,xml和json格式数据导出
- 仪表板页面和小部件支持
- 现场书签
- 完整的CURD方法(增删改查)
二、xadmin安装与配置
安装
pip install xadmin2
配置settings.py
代码语言:javascript复制INSTALLED_APPS = [
....
<span class="hljs-string">'xadmin'</span>,
<span class="hljs-string">'crispy_forms'</span>,
]
<span class="hljs-comment"># 修改使用中文界面</span>
LANGUAGE_CODE = <span class="hljs-string">'zh-Hans'</span>
<span class="hljs-comment"># 修改时区</span>
TIME_ZONE = <span class="hljs-string">'Asia/Shanghai'</span>
配置路由
代码语言:javascript复制<span class="hljs-keyword">import</span> xadmin
urlpatterns = [
<span class="hljs-comment"># path('admin/', admin.site.urls),</span>
path(<span class="hljs-string">'xadmin/'</span>, xadmin.site.urls),
]
执行迁移 创建xadmin所需表
python manage.py migrate
创建用户
python manage.py createsuperuser
三、模型类
班级表
代码语言:javascript复制<span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models
<span class="hljs-comment"># Create your models here.</span>
<span class="hljs-comment"># 班级表</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Grades</span><span class="hljs-params">(models.Model)</span>:</span>
gname = models.CharField(max_length=<span class="hljs-number">15</span>, verbose_name=<span class="hljs-string">'班级名称'</span>)
gnum = models.IntegerField(verbose_name=<span class="hljs-string">'班级总人数'</span>)
ggirlnum = models.IntegerField(verbose_name=<span class="hljs-string">'女生人数'</span>)
gboynum = models.IntegerField(verbose_name=<span class="hljs-string">'男生人数'</span>)
isDelete = models.BooleanField(default=<span class="hljs-keyword">False</span>, verbose_name=<span class="hljs-string">'是否删除'</span>)
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span><span class="hljs-params">(self)</span>:</span>
<span class="hljs-keyword">return</span> self.gname
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
db_table = <span class="hljs-string">'grades'</span>
学生表
代码语言:javascript复制<span class="hljs-comment"># 学生表</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Students</span><span class="hljs-params">(models.Model)</span>:</span>
sname = models.CharField(max_length=<span class="hljs-number">10</span>, verbose_name=<span class="hljs-string">'学生名字'</span>)
ssex = models.BooleanField(default=<span class="hljs-keyword">True</span>, verbose_name=<span class="hljs-string">'性别'</span>)
sage = models.IntegerField(default=<span class="hljs-number">20</span>, verbose_name=<span class="hljs-string">'年龄'</span>)
sgrade = models.ForeignKey(Grades, on_delete=models.CASCADE, verbose_name=<span class="hljs-string">'班级'</span>)
isDelete = models.BooleanField(default=<span class="hljs-keyword">False</span>, verbose_name=<span class="hljs-string">'是否删除'</span>)
join = models.DateField(auto_now_add=<span class="hljs-keyword">True</span>)
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span><span class="hljs-params">(self)</span>:</span>
<span class="hljs-keyword">return</span> self.sname
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
db_table = <span class="hljs-string">'students'</span>
四、Xadmin使用
增加用户组件报错解决
原因:render函数在django2.1上有变化
解决方案:
在Python终端输入命令help(‘xadmin’) 查看xadmin安装位置 得到如下输出
代码语言:javascript复制FILE
/Users/xialigang/Desktop/do_xadmin/venv/lib/python3<span class="hljs-number">.7</span>/site-packages/xadmin/__init__.py
代码语言:javascript复制
进入xadmin安装路径,编辑xadmin/views/dashboard.py
代码语言:javascript复制 <span class="hljs-number">36</span> <span class="hljs-comment">#render() got an unexpected keyword argument 'renderer'</span>
<span class="hljs-number">37</span> <span class="hljs-comment">#修改bug, 添加renderer</span>
<span class="hljs-number">38</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">render</span><span class="hljs-params">(self, name, value, attrs=None, renderer=None)</span>:</span>
设置app标题
App/apps.py
代码语言:javascript复制rom django.apps <span class="hljs-keyword">import</span> AppConfig
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppConfig</span><span class="hljs-params">(AppConfig)</span>:</span>
<span class="hljs-comment"># app名</span>
name = <span class="hljs-string">'App'</span>
verbose_name = <span class="hljs-string">'模型管理'</span>
代码语言:javascript复制App/__init__.py
```python
default_app_config='App.apps.AppConfig'
站点的全局配置
主题配置
- enable_themes = True 开启主题切换功能
use_bootswatch = True 支持切换主题
全局配置
site_title = “lucky 后台管理系统” 设置站点标题
site_footer = “lucky底部栏” 设置站点的页脚
menu_style = “accordion” 设置菜单折叠,在左侧,默认的
- global_search_models = [Grades, Students] 设置全局搜索模型
global_models_icon 设置models的全局图标
代码语言:javascript复制 global_models_icon = {
Grades: <span class="hljs-string">"glyphicon glyphicon-user"</span>, Students: <span class="hljs-string">"fa fa-cloud"</span>
}
实例
代码语言:javascript复制 <span class="hljs-keyword">import</span> xadmin
<span class="hljs-keyword">from</span> xadmin <span class="hljs-keyword">import</span> views
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BaseSetting</span><span class="hljs-params">(object)</span>:</span>
<span class="hljs-string">"""xadmin的基本配置"""</span>
enable_themes = <span class="hljs-keyword">True</span> <span class="hljs-comment"># 开启主题切换功能</span>
use_bootswatch = <span class="hljs-keyword">True</span> <span class="hljs-comment"># 支持切换主题</span>
xadmin.site.register(views.BaseAdminView, BaseSetting)
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GlobalSettings</span><span class="hljs-params">(object)</span>:</span>
<span class="hljs-string">"""xadmin的全局配置"""</span>
site_title = <span class="hljs-string">"lucky后台管理系统"</span> <span class="hljs-comment"># 设置站点标题</span>
site_footer = <span class="hljs-string">"lucky底部栏"</span> <span class="hljs-comment"># 设置站点的页脚</span>
menu_style = <span class="hljs-string">"accordion"</span> <span class="hljs-comment"># 设置菜单折叠,在左侧,默认的</span>
global_search_models = [Grades, Students]
<span class="hljs-comment"># 设置models的全局图标, Grades, Students 为模型类名</span>
global_models_icon = {
Grades: <span class="hljs-string">"glyphicon glyphicon-user"</span>, Students: <span class="hljs-string">"fa fa-cloud"</span>
}
xadmin.site.register(views.CommAdminView, GlobalSettings)
模型类配置属性与实例
菜单的图标
model_icon
代码语言:javascript复制model_icon = <span class="hljs-string">'fa fa-image'</span>
列表显示内容
list_display
代码语言:javascript复制list_display = (<span class="hljs-string">'pk'</span>, <span class="hljs-string">'gname'</span>, <span class="hljs-string">'gnum'</span>, <span class="hljs-string">'ggirlnum'</span>, <span class="hljs-string">'gboynum'</span>, <span class="hljs-string">'isDelete'</span>)
设置默认可编辑字段
list_display_links
代码语言:javascript复制list_display_links = (<span class="hljs-string">'gname'</span>, <span class="hljs-string">'gnum'</span>)
分页显示
list_per_page
代码语言:javascript复制list_per_page = <span class="hljs-number">2</span>
显示数据详情
show_detail_fields
代码语言:javascript复制show_detail_fields = [<span class="hljs-string">'gname'</span>]
指定列表页的数据定时刷新
refresh_times
代码语言:javascript复制refresh_times=(<span class="hljs-number">3</span>,<span class="hljs-number">5</span>) <span class="hljs-comment"># 3/5秒进行刷新</span>
该指定可以过滤的列的名字, 系统会自动生成搜索器
list_filter
代码语言:javascript复制list_filter = (<span class="hljs-string">'gname'</span>,)
表单显示内容
fields
代码语言:javascript复制fields = (<span class="hljs-string">'gname'</span>, <span class="hljs-string">'gnum'</span>, <span class="hljs-string">'ggirlnum'</span>, <span class="hljs-string">'gboynum'</span>, <span class="hljs-string">'isDelete'</span>)
搜索字段
search_fields
代码语言:javascript复制search_fields = (<span class="hljs-string">'gname'</span>, <span class="hljs-string">'gnum'</span> )
模型类配置使用实例
代码语言:javascript复制<span class="hljs-keyword">from</span> App.models <span class="hljs-keyword">import</span> Grades, Students
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GradesAdmin</span><span class="hljs-params">(object)</span>:</span>
<span class="hljs-comment"># 菜单的图标</span>
model_icon = <span class="hljs-string">'fa fa-image'</span>
<span class="hljs-comment"># 列表显示内容</span>
list_display = (<span class="hljs-string">'pk'</span>, <span class="hljs-string">'gname'</span>, <span class="hljs-string">'gnum'</span>, <span class="hljs-string">'ggirlnum'</span>, <span class="hljs-string">'gboynum'</span>, <span class="hljs-string">'isDelete'</span>)
<span class="hljs-comment"># 设置默认可编辑字段</span>
list_display_links = (<span class="hljs-string">'gname'</span>, <span class="hljs-string">'gnum'</span>)
<span class="hljs-comment"># 分页显示</span>
list_per_page = <span class="hljs-number">2</span>
<span class="hljs-comment"># 显示数据详情 </span>
show_detail_fields = [<span class="hljs-string">'gname'</span>]
<span class="hljs-comment"># 3/5秒进行刷新</span>
refresh_times=(<span class="hljs-number">3</span>,<span class="hljs-number">5</span>)
<span class="hljs-comment"># 过滤器</span>
list_filter = (<span class="hljs-string">'gname'</span>,)
<span class="hljs-comment"># 表单显示内容</span>
fields = (<span class="hljs-string">'gname'</span>, <span class="hljs-string">'gnum'</span>, <span class="hljs-string">'ggirlnum'</span>, <span class="hljs-string">'gboynum'</span>, <span class="hljs-string">'isDelete'</span>)
<span class="hljs-comment"># 搜索字段</span>
search_fields = (<span class="hljs-string">'gname'</span>, <span class="hljs-string">'gnum'</span> )
xadmin.site.register(Grades, GradesAdmin)
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StudentsAdmin</span><span class="hljs-params">(object)</span>:</span>
<span class="hljs-comment"># 菜单的图标</span>
model_icon = <span class="hljs-string">'fa fa-image'</span>
<span class="hljs-comment"># 列表显示内容</span>
list_display = (<span class="hljs-string">'pk'</span>,<span class="hljs-string">'sname'</span>, <span class="hljs-string">'ssex'</span>, <span class="hljs-string">'sage'</span>, <span class="hljs-string">'sgrade'</span>)
<span class="hljs-comment"># list_display_links 设置默认可编辑字段</span>
list_display_links = (<span class="hljs-string">'sname'</span>, <span class="hljs-string">'sage'</span>)
<span class="hljs-comment"># 分页显示</span>
list_per_page = <span class="hljs-number">2</span>
<span class="hljs-comment"># 过滤器</span>
list_filter = (<span class="hljs-string">'sname'</span>,)
<span class="hljs-comment"># 表单显示内容</span>
fields = (<span class="hljs-string">'sname'</span>,<span class="hljs-string">'ssex'</span>, <span class="hljs-string">'sage'</span>, <span class="hljs-string">'sgrade'</span>, <span class="hljs-string">'isDelete'</span>)
<span class="hljs-comment"># 搜索字段</span>
search_fields = (<span class="hljs-string">'sname'</span>, <span class="hljs-string">'sage'</span> )
xadmin.site.register(Students, StudentsAdmin)
图表主要属性
- title 图表的显示名称
- x-field 图表的 X 轴数据列, 一般是日期, 时间等
- y-field 图表的 Y 轴数据列, 该项是一个 list, 可以同时设定多个列, 这样多个列的数据会在同一个图表中显示
- order 排序信息, 如果不写则使用数据列表的排序
配置students走势展示图表
代码语言:javascript复制<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StudentsAdmin</span><span class="hljs-params">(object)</span>:</span>
...
data_charts = {
<span class="hljs-string">"students_count"</span>: {<span class="hljs-string">'title'</span>: <span class="hljs-string">"Students Register Charts"</span>, <span class="hljs-string">"x-field"</span>: <span class="hljs-string">"join"</span>, <span class="hljs-string">"y-field"</span>: (<span class="hljs-string">"id"</span>,),
<span class="hljs-string">"order"</span>: (<span class="hljs-string">'join'</span>,)},
}
自定义导航菜单顺序
代码语言:javascript复制<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GlobalSettings</span><span class="hljs-params">(object)</span>:</span>
<span class="hljs-string">"""xadmin的全局配置"""</span>
...
<span class="hljs-comment"># 菜单顺序</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_site_menu</span><span class="hljs-params">(self)</span>:</span>
<span class="hljs-keyword">return</span> (
{<span class="hljs-string">'title'</span>: <span class="hljs-string">'模型管理'</span>, <span class="hljs-string">'menus'</span>: (
{<span class="hljs-string">'title'</span>: <span class="hljs-string">'班级信息'</span>, <span class="hljs-string">'url'</span>: self.get_model_url(Grades, <span class="hljs-string">'changelist'</span>), <span class="hljs-string">'icon'</span>: <span class="hljs-string">'glyphicon glyphicon-user'</span>},
{<span class="hljs-string">'title'</span>: <span class="hljs-string">'学生信息'</span>, <span class="hljs-string">'url'</span>: self.get_model_url(Students, <span class="hljs-string">'changelist'</span>), <span class="hljs-string">'icon'</span>:<span class="hljs-string">'fa fa-cloud'</span>},
)},
)
xadmin.site.register(views.CommAdminView, GlobalSettings)
注意:参数changelist为固定值
设置只读字段
说明:在使用xadmin的时候,ModelAdmin默认只有对于model的增删改查,但是总是有些字段是不希望用户来编辑的。而 readonly_fields 设置之后不管是admin还是其他用户都会变成只读,而我们通常只是想限制普通用户。 这时我们就可以通过重写 get_readonly_fields 方法来实现对特定用户的只读显示
代码语言:javascript复制<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StudentsAdmin</span><span class="hljs-params">(object)</span>:</span>
...
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_readonly_fields</span><span class="hljs-params">(self, **kwargs)</span>:</span>
<span class="hljs-string">""" 重新定义此函数,限制普通用户所能修改的字段 """</span>
print(self.org_obj)
<span class="hljs-keyword">if</span> self.user.is_superuser:
self.readonly_fields = []
<span class="hljs-keyword">return</span> self.readonly_fields
readonly_fields = (<span class="hljs-string">'sname'</span>,)
list_display使用自定义函数
需求:性别改为男女
代码语言:javascript复制<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StudentsAdmin</span><span class="hljs-params">(object)</span>:</span>
<span class="hljs-comment"># 菜单的图标</span>
model_icon = <span class="hljs-string">'fa fa-image'</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">gender</span><span class="hljs-params">(self, obj)</span>:</span>
<span class="hljs-keyword">if</span> obj.ssex:
<span class="hljs-keyword">return</span> <span class="hljs-string">"男"</span>
<span class="hljs-keyword">else</span>:
<span class="hljs-keyword">return</span> <span class="hljs-string">"女"</span>
gender.short_description = <span class="hljs-string">'性别'</span>
<span class="hljs-comment"># 列表显示内容</span>
list_display = (<span class="hljs-string">'pk'</span>,<span class="hljs-string">'sname'</span>, <span class="hljs-string">'gender'</span>, <span class="hljs-string">'sage'</span>, <span class="hljs-string">'sgrade'</span>)
...
inlines 机制
说明:如果想添加数据的同时方便添加关联model,inlines 机制 同一个页面 可以添加 所有的相关信息
需求:在添加班级的时候添加几个学生
代码语言:javascript复制<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StudentsInline</span>:</span>
model = Students <span class="hljs-comment"># 要添加数据关联模型</span>
extra = <span class="hljs-number">2</span> <span class="hljs-comment"># 添加数据的条数</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GradesAdmin</span><span class="hljs-params">(object)</span>:</span>
inlines = [StudentsInline]
注意:还可以在修改班级的时候修改对应关联模型的数据
添加数据
修改数据
重载修改显示样式
说明:在要改变数据时候样式的模型类Admin添加如下代码
代码语言:javascript复制<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StudentsAdmin</span><span class="hljs-params">(object)</span>:</span>
...
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_form_layout</span><span class="hljs-params">(self)</span>:</span>
<span class="hljs-keyword">if</span> self.org_obj:
self.form_layout = (
Main(
Fieldset(<span class="hljs-string">''</span>,
<span class="hljs-string">'sname'</span>,
css_class=<span class="hljs-string">'unsort no_title'</span> <span class="hljs-comment"># 没有标题</span>
),
Fieldset((<span class="hljs-string">'基本信息'</span>),
Row(<span class="hljs-string">'ssex'</span>, <span class="hljs-string">'sage'</span>), <span class="hljs-comment"># 显示在一行</span>
<span class="hljs-string">'email'</span>
),
Fieldset((<span class="hljs-string">'班级信息'</span>),
<span class="hljs-string">'sgrade'</span>
),
),
Side( <span class="hljs-comment"># 侧面展示</span>
Fieldset((<span class="hljs-string">'Status'</span>),
<span class="hljs-string">'isDelete'</span>
),
)
)
<span class="hljs-keyword">return</span> super().get_form_layout()
模型编辑页面Field分区显示–form_layout
在admin.py中我们可以通过Fieldsets去设置字段的分块显示 界面显示会上下分区,分为名字为空和名字为其它的两个区域。
而在xadmin.py中,这个字段不再生效,需用form_layout去设置。
可分为Main主区域和Side侧边区域,Main或Side中又可通过Fieldset再分多个区域。Fieldset为一个元组,第一个字段为需要设置的名称,其它字段均为模型中的字段名
如下:
代码语言:javascript复制<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StudentsAdmin</span><span class="hljs-params">(object)</span>:</span>
...
form_layout = (
Main(
Fieldset(<span class="hljs-string">'基础信息'</span>,
<span class="hljs-string">'sname'</span>),
Fieldset(<span class="hljs-string">'EXTRA'</span>,
<span class="hljs-string">'ssex'</span>, <span class="hljs-string">'sage'</span>, <span class="hljs-string">'sgrade'</span>),
),
Side(
Fieldset(<span class="hljs-string">'其它'</span>,
<span class="hljs-string">'isDelete'</span>),
)
)
注意:如果form_layout与get_form_layout同时存在 则form_layout仅在添加数据的时候进行分区样式展示 如果get_form_layout不存在 则添加与修改都进行分区显示
增加页面显示列的跳转
显示自定义的html代码
models.py
代码语言:javascript复制<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Grade</span><span class="hljs-params">(models.Model)</span>:</span>
.
.
.
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">go_to</span><span class="hljs-params">(self)</span>:</span>
<span class="hljs-keyword">from</span> django.utils.safestring <span class="hljs-keyword">import</span> mark_safe
<span class="hljs-comment"># mark_safe后就不会转义</span>
<span class="hljs-keyword">return</span> mark_safe(<span class="hljs-string">"<a href='http://www.baidu.com'>跳转</a>"</span>)
go_to.short_description = <span class="hljs-string">"跳转"</span>
admin.py
代码语言:javascript复制<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GradeAdmin</span><span class="hljs-params">(object)</span>:</span>
list_display = [<span class="hljs-string">'go_to'</span>]