xadmin快速搭建后台管理系统
一.xadmin的特点:
1.基于Bootstrap3:Xadmin使用Bootstrap3.0框架精心打造。基于Bootstrap3,Xadmin天生就支持在多种屏幕上无缝浏览,并完全支持Bootstrap主题模板,让您的管理后台也动感、多样起来。
2.内置功能丰富:Xadmin作为一款全面的后台管理系统框架,不仅提供了基本的CRUD功能,还内置了丰富的插件功能。包括数据导出、书签、图表、数据添加向导及图片相册等多种扩展功能。
3.真心强大的插件系统:Xadmin的插件系统借鉴了其他领域成功框架的设计思想,让插件可以扩展系统的任何一个功能点。对于开发者,Xadmin的插件开发简单;对于使用者,Xadmin的插件安装方便。
4.后台实际就是对表的增删改查,从某种程度上来讲不依赖于业务逻辑,又可以在后台对每张表管理时加入自己的后台逻辑,这也是它优于很多后台管理系统的原因。
二.xadmin的安装:
1.直接通过pip安装:pip install xadmin(会有三个依赖包:django-formtools ,django-crispy-forms ,httplib2 都会自动安装好)
2.通过githup上搜索xadmin,直接下载源码包,只需把下载文件中的xadmin文件夹拷贝到项目根目录配置便可以使用,当然得把pip安装得xadmin卸载后使用的才是导入的源码包–pip uninstall xadmin(推荐,当xadmin的新功能还没有发布到pypi上时,可以优先使用,当然,最主要的是我们可以查看源码,更加容易理解xadmin的功能,并在不断学习中进步)
三.xadmin的app配置及url配置:
1.app配置:xadmin是一个app,也应该在setting.py的INSTALLED_APPS中添加上,不只是xadmin,还得添加上依赖包crispy_forms。
INSTALLED_APPS = [ \'django.contrib.admin\', \'django.contrib.auth\', \'django.contrib.contenttypes\', \'django.contrib.sessions\', \'django.contrib.messages\', \'django.contrib.staticfiles\', \'xadmin\', \'crispy_forms\' ]
2.url配置:替换Django自带的admin,将url指向xadmin
import xadmin urlpatterns = [ url(r\'^xadmin/\', xadmin.site.urls), ]
3.此时访问xadmin的url(我使用的默认端口,为127.0.0.1:8000/xadmin),会提示Table ‘xxx.xadmin_usersettings\’ doesn\’t exist,是因为xadmin有一些默认的表,只需要同步即可,从新makemigrations(生成数据库脚本文件),migrate(生成更新表),便可以发现数据库多了几张以xadmin开头的表(图1),从新启动项目便可以访问了。
图1
4.访问成功后,进入用户表效果如图2(布局不像admin一每一列一个字段,而且密码被加密,并告诉加密算法,相比admin更加安全美化,布局可自己定制):
图2
四.xadmin的使用:
1.在每一个app下新建一个adminx.py文件(类似django自动生成的admin.py文件,xadmin会自动在每个app下搜索xadminx.py并注册)
2.xadmin的简单注册(以School表为例),效果如图3:
#导入xamin模块 import xadmin #导入School表 from .models import School #创建注册类 class SchoolAdmin(object): pass xadmin.site.register(School, SchoolAdmin)
图3
class School(models.Model): \'\'\' 学校表 \'\'\' name=models.CharField(max_length=50,verbose_name=\'学校名字\') address=models.CharField(max_length=100,verbose_name=\'学校地址\') add_time=models.DateTimeField(default=datetime.now,verbose_name=\'添加时间\') class Meta: verbose_name=\'学校\' verbose_name_plural=verbose_name def __str__(self): return self.name
图4
注册在后台的标名为verbose_name(数据只有一条,即单数),否则为verbose_name_plural(数据大于一条,即为复数),若为指明verbose_name_plural,则复数形式默认在单数形式后面在s(学校s),进入详情页的标签则为models中的verbose_name。models中重载__str__()函数返回的值是在每张表详情列表页的展示的标签名,可以在显示列中指定,如图5,以及点进详情页的修改(删除)xxx的标签名,如图3(修改西南石油大学)。
3.list_display的使用:指定默认展示列(效果如图5),注:要想过滤某外键下的字段,只需xxx__yy(xxx为该表字段名,yy为外键对应表字段),效果如图6
class SchoolAdmin(object): #可以是列表[],也可以是元组(),但使用元组只有一个字段是一定要加逗号 list_display=[\'name\',\'address\'] #每页显示多少个 list_per_page=20
class Sport_FavAdmin(object): list_display = [\'student\', \'sport\', \'add_time\'] search_fields = [\'student\', \'sport\'] #student,sport均为外键,username,sport_name分别为学生表,运动项目表下的字段 list_filter = [\'student__username\', \'sport__sport_name\', \'add_time\']
图5
图6
4.search_fields的使用:搜索功能(包含搜索,即字段包含搜索字段便可以搜索出,一般不做时间功能搜索),会多出一个搜索框,可以在里面搜索配置好了的字段,如图6
class SchoolAdmin(object): # 可以是列表[],也可以是元组(),但使用元组只有一个字段是一定要加逗号 list_display=[\'name\',\'address\'] #配置在哪些字段搜索 search_fields=[\'name\',\'address\']
图7
5.list_filter的使用:筛选功能(如对时间筛选),会多出一个过滤器,便可以进行过滤搜索了,使开发变得简单,如图7
class SchoolAdmin(object): # 可以是列表[],也可以是元组(),但使用元组只有一个字段是一定要加逗号 list_display=[\'name\',\'address\'] #配置在哪些字段搜索 search_fields=[\'name\',\'address\'] #配置过滤字段 list_filter=[\'name\',\'address\',\'add_time\']
图8
6.xadmin全局配置,app名称修改,左侧样式布局:
主题配置:注册与表注册不同,需要将类和views.BaseAdminView绑定,且顺序与表相反,效果如图9
from xadmin import views class BaseSetting(object): \'\'\' 主题样式多样化 \'\'\' enable_themes=True use_bootswatch=True xadmin.site.register(views.BaseAdminView,BaseSetting)
图9
标签配置,效果如图10:
from xadmin import views class GlobalSetting(object): #页头 site_title = \'悦动乐后台管理系统\' #页脚 site_footer = \'悦动乐\' xadmin.site.register(views.CommAdminView, GlobalSetting)
图10
将app下表以下拉形式展开(折叠样式),效果如图11:
class GlobalSetting(object): #页头 site_title = \'悦动乐后台管理系统\' #页脚 site_footer = \'悦动乐\' #左侧样式 menu_style=\'accordion\'
图11
修改app名称:
只需修改每个app下的app.py文件,在config类中加上verbose_name=xxx,然后在对应__init__.py文件中加上default_app_config=\’对应config路径\’,效果如图12。
app.py配置:
from django.apps import AppConfig class UsersConfig(AppConfig): name = \'users\' verbose_name=\'用户管理\'
__init__.py配置:
default_app_config=\'users.apps.UsersConfig\'
图12
设置全局图标,效果如图13,对应图标代码可参考http://v3.bootcss.com/components/和http://www.yeahzan.com/fa/facss.html
class GlobalSetting(object): #页头 site_title = \'悦动乐后台管理系统\' #页脚 site_footer = \'悦动乐\' #左侧样式 menu_style=\'accordion\' # 设置models的全局图标 global_search_models = [UserProfile, Sports] global_models_icon = { UserProfile: "glyphicon glyphicon-user", Sports: "fa fa-cloud" }
图13
model_icon的使用:配置表的图标,可以在awesome官网上下载最新的font-awesome.css替换,并找寻到相应的icon书写
class Sport_FavAdmin(object): list_display = [\'student\', \'sport\', \'add_time\'] search_fields = [\'student\', \'sport\'] list_filter = [\'student__username\', \'sport__sport_name\', \'add_time\'] #相应表图标配置 model_icon=\'fa fa-address-book\'
显示数据详情,如图14:
class Sport_FavAdmin(object): list_display = [\'student\', \'sport\', \'add_time\'] search_fields = [\'student\', \'sport\'] list_filter = [\'student__username\', \'sport__sport_name\', \'add_time\'] #显示详情 show_detail_fields=[\'sport\']
图14
设置刷新时间,图15:
class Sport_FavAdmin(object): list_display = [\'student\', \'sport\', \'add_time\'] search_fields = [\'student\', \'sport\'] list_filter = [\'student__username\', \'sport__sport_name\', \'add_time\'] #显示详情 show_detail_fields=[\'sport\'] #数据刷新时间 refresh_times=(3,5)
图15
书签:数据列表页面特定的数据过滤,排序等结果,添加的书签还可以在首页仪表盘中作为小组件添加。
图表:在数据列表页面,根据列表数据生成图表,可以指定多个数据列,生成多个图表。在Model OptionClass 中设定data_charts属性,该属性为dict类型,key是图表的标示名称,value是图表的具体设置属性,示例:
data_charts = { "user_count": {\'title\': u"约运动", "x-field": "sport_time", "y-field": ("people_nums",), }, }
图表属性:
title : 图表的显示名称
x-field : 图表的 X 轴数据列, 一般是日期, 时间等
y-field : 图表的 Y 轴数据列, 该项是一个 list, 可以同时设定多个列, 这样多个列的数据会在同一个图表中显示
order : 排序信息, 如果不写则使用数据列表的排序
效果如图16:
图16
数据导出:如果想要导出Excel数据,需要安装xlwt。默认情况下,xadmin会提供Excel,CSV,XML,json四种格式的数据导出,可以通过设置OptionClass的list_export属性来指定使用哪些导出格式(四种格式分别用xls,csv,xml,json表示)或是将list_export设置为None来禁用数据导出功能。效果如图17
class ScheduleAdmin(object): list_display = [\'start_people\', \'sport\', \'sport_time\', \'people_nums\'] search_fields = [\'start_people\', \'sport\', \'sport_time\', \'people_nums\'] list_filter = [\'start_people\', \'sport\', \'sport_time\', \'people_nums\', \'add_time\'] #导出类型 list_export = (\'xls\', \'xml\', \'json\') #导出字段 list_export_fields = (\'start_people\', \'sport\', \'sport_time\')
图17
其他:不一一详细介绍,用到时可以查看
#对应相应的model class LessonInline(object): model=Lesson extra=0 class CourseResourceInline(object): model=CourseResource extra=0 #配置默认排序规则 ordering=[\'-people_nums\'] #设置未只读,不能修改 readonly_fields=[\'proplr_nums\'] #设置为后台不能看见,与readony_fields冲突,有前者,exclude不生效 exclude=[\'fav_nums\'] # 设置添加时可以搜索,而不是下拉框,ajax加载(外键) relfield_style = \'fk-ajax\' #在同一个页面添加完整数据,不可以在嵌套中嵌套,但可以多个,同一个model注册两个管理器 inlines=[LessonInline,CourseResourceInline] #列表页直接修改的字段 list_editable=[\'degree\',\'desc\']
#定制分类管理,筛选,调用当前admin
def queryset(self):
qs=super(BannerCourseAdmin,self).queryset()
qs=qs.filter(is_banner=True)
return qs
权限介绍:默认生成对每个表的增删改查权限,勾上是否职员,用户便可以登录后台管理系统,若没赋予权限,则什么也不可以干,如图18,赋予权限,如图19,方便管理可以把用户放入权限组:
图18
图19
文本编辑器集成及插件导入(较重要):
xadmin集成富文本框(可在githup上查看相关配置):
DjangoUeditor的安装:1.下载源码包,然后python setup.py install;2.pip install DjangoUeditor
然后在setting.py中配置app:
INSTALLED_APPS = [ ....... \'DjangoUeditor\', ]
配置url:
url(r\'^ueditor/\',include(\'DjangoUeditor.urls\' )),
修改models:
from DjangoUeditor.models import UEditorField ...... #width:宽,height:高,imagePath,filePath图片文件上传路径 detail = UEditorField(verbose_name=u"运动详情",width=600, height=300, imagePath="courses/ueditor/", filePath="courses/ueditor/", default=\'\')
ueditor插件定制,在\extra_apps\xadmin\plugins添加ueditor.py如下:
import xadmin from xadmin.views import BaseAdminPlugin, CreateAdminView, ModelFormAdminView, UpdateAdminView from DjangoUeditor.models import UEditorField from DjangoUeditor.widgets import UEditorWidget from django.conf import settings class XadminUEditorWidget(UEditorWidget): def __init__(self,**kwargs): self.ueditor_options=kwargs self.Media.js = None super(XadminUEditorWidget,self).__init__(kwargs) class UeditorPlugin(BaseAdminPlugin): def get_field_style(self, attrs, db_field, style, **kwargs): if style == \'ueditor\': if isinstance(db_field, UEditorField): widget = db_field.formfield().widget param = {} param.update(widget.ueditor_settings) param.update(widget.attrs) return {\'widget\': XadminUEditorWidget(**param)} return attrs def block_extrahead(self, context, nodes): js = \'<script type="text/javascript" src="%s"></script>\' % (settings.STATIC_URL + "ueditor/ueditor.config.js") #自己的静态目录 js += \'<script type="text/javascript" src="%s"></script>\' % (settings.STATIC_URL + "ueditor/ueditor.all.min.js") #自己的静态目录 nodes.append(js) xadmin.site.register_plugin(UeditorPlugin, UpdateAdminView) xadmin.site.register_plugin(UeditorPlugin, CreateAdminView)
plugin配置:在extra_apps\xadmin\plugins\__init__.py中配置:
PLUGINS = ( \'actions\', \'filters\', \'bookmark\', \'export\', \'layout\', \'refresh\', \'details\', \'editable\', \'relate\', \'chart\', \'ajax\', \'relfield\', \'inline\', \'topnav\', \'portal\', \'quickform\', \'wizard\', \'images\', \'auth\', \'multiselect\', \'themes\', \'aggregation\', \'mobile\', \'passwords\', \'sitemenu\', \'language\', \'quickfilter\', \'sortablelist\', #ueditor配置,与uditor.py文件名一致 \'ueditor\',
#excel插件设置 \'excel\']
admin样式定制:
class SportAdmin(object): #定义样式 style_fields={"detail":"ueditor"}
防止前端转义 :template取值时
#关闭转义 {% autoescape off%} {{ xxx.detail }} {% endautoescape %}
excel插件的导入,效果如图20:
图20
excel插件定制,在\extra_apps\xadmin\plugins添加excel.py如下:
# coding:utf-8 import xadmin from xadmin.views import BaseAdminPlugin, ListAdminView from django.template import loader #excel 导入 class ListImportExcelPlugin(BaseAdminPlugin): import_excel = False def init_request(self, *args, **kwargs): return bool(self.import_excel) def block_top_toolbar(self, context, nodes):
#html文件 nodes.append(loader.render_to_string(\'xadmin/excel/model_list.top_toolbar.import.html\', context_instance=context)) xadmin.site.register_plugin(ListImportExcelPlugin, ListAdminView)
html文件定制,在extra_apps\xadmin\templates\xadmin\excel\model_list.top_toolbar.import.html:
function fileChange(target){ //检测上传文件的类型 var imgName = document.all.submit_upload.value; var ext,idx; if (imgName == \'\'){ document.all.submit_upload_b.disabled=true; alert("请选择需要上传的 xls 文件!"); return; } else { idx = imgName.lastIndexOf("."); if (idx != -1){ ext = imgName.substr(idx+1).toUpperCase(); ext = ext.toLowerCase( ); {# alert("ext="+ext);#} if (ext != \'xls\' && ext != \'xlsx\'){ document.all.submit_upload_b.disabled=true; alert("只能上传 .xls 类型的文件!"); return; } } else { document.all.submit_upload_b.disabled=true; alert("只能上传 .xls 类型的文件!"); return; } } }
后台逻辑:
......Admin(object): #导入excel插件 import_excel = True def post(self,request,*args,**kwargs): if \'excel\' in request.FILES: pass #必须返回,不然报错(或者注释掉) return super(CourseAdmin,self).post(request,*args,**kwargs)
注:user表默认注册到认证和授权app中,如果需要将其移到用户管理app中,且定制可以查看extra_apps\xadmin\plugins\auth.py,修改相应配置即可定制布局,只需如下,如果Django版本大于2.0,需修改相应文件名及相关配置才能使用:
第一种方法:
#导入关联用户表的Admin from xadmin.plugins.auth import UserAdmin from users.models import UserProfile class UserAdmin(UserAdmin): \'\'\' 注册User到用户管理 \'\'\' pass from django.contrib.auth.models import User #卸载自带的User注册 xadmin.site.unregister(User) xadmin.site.register(UserProfile,UserAdmin)
第二种方法:在extra_apps\xadmin\plugins\auth.py中加入如下,如果在点击如图18的修改密码时报错,也需加入如下代码(xadmin的bug,后面可能已经修复)
图21
#获取setting中的User from django.contrib.auth import get_user_model User = get_user_model()
还有可能点击用户详情中修改密码的this form报404错误,如图20
图22
只需修改extra_apps\xadmin\plugins\auth.py注册时成setting.py对应的url即可:
#修改修改passwoed的url,我的是users/userprofile/(.+)/password site.register_view(r\'^users/userprofile/(.+)/password/$\', ChangePasswordView, name=\'user_change_password\')