xadmimn简介
Xadmin采用python语言编写,基于Bootstrap3,内置功能丰富
github地址: https://github.com/sshwsfc/xadmin
本人建议:由于Xadmin已经不维护,本文仅以学习为主。
学完Xadmin,如想了解更多python的后台管理系统,推荐https://github.com/happybeta/simpleui 和 https://github.com/mtianyan/django-antd-tyadmin
下载源码后,拖入项目中,安装xadmin需要的相关依赖,执行migrate,生成xadmin所需要的表
xadmin会自动发现我们自定义的用户表并自动生成
1 2 3 4 5 6 7 8 9 10 11 12
| class UserProfile(AbstractUser): nick_name = models.CharField(max_length=50, verbose_name="昵称", default="") birthday = models.DateField(verbose_name="生日", null=True, blank=True) gender = models.CharField(verbose_name="性别", choices=GENDER_CHOICES, max_length=6) address = models.CharField(max_length=100, verbose_name="地址", default="") mobile = models.CharField(max_length=11, verbose_name="手机号码") image = models.ImageField(verbose_name="用户头像", upload_to="head_image/%Y/%m", default="default.jpg")
class Meta: verbose_name = "用户信息" verbose_name_plural = verbose_name
|
简单使用
自定义后台管理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from apps.organizations.models import Teacher class CityAdmin(object): list_display = ["id", "name", "desc"] search_fields = ["name", "desc"] list_filter = ["name", "desc", "add_time"] list_editable = ["name", "desc"]
xadmin.site.register(City, CityAdmin)
|
全局配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class GlobalSettings(object): site_title = "eu课堂后台管理系统" site_footer = "eu课堂" menu_style = "accordion"
class BaseSettings(object): enable_themes = True use_bootswatch = True
|
更高级的使用
自定义表的详情页面
重写get_form_layout方法
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| class NewCourseAdmin(object): ... list_display = ['name', 'desc', 'show_image', 'go_to', 'detail', 'degree', 'learn_times', 'students'] search_fields = ['name', 'desc', 'detail', 'degree', 'students'] list_filter = ['name', 'teacher__name', 'desc', 'detail', 'degree', 'learn_times', 'students'] ... def get_form_layout(self): if self.org_obj: self.form_layout = ( Main( Fieldset("讲师信息", 'teacher', 'course_org', css_class='unsort no_title' ), Fieldset("基本信息", 'name', 'desc', Row('learn_times', 'degree'), Row('category', 'tag'), 'youneed_know', 'teacher_tell', 'detail', ), ), Side( Fieldset("访问信息", 'fav_nums', 'click_nums', 'students', 'add_time' ), ), Side( Fieldset("选择信息", 'is_banner', 'is_classics' ), ) ) return super(NewCourseAdmin, self).get_form_layout()
|
组和权限的概念
可以给每个用户设置权限,不同的权限对应不同的功能;如果需要对多个用户设置权限,则需要添加一个组,对组配置权限,再将用户选中为某个组,那么该用户便有了那个组的权限。
不同用户登录时返回不同的数据
重写queryset方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class NewCourseAdmin(object): ... list_display = ['name', 'desc', 'show_image', 'go_to', 'detail', 'degree', 'learn_times', 'students'] search_fields = ['name', 'desc', 'detail', 'degree', 'students'] list_filter = ['name', 'teacher__name', 'desc', 'detail', 'degree', 'learn_times', 'students'] ...
def queryset(self): qs = super().queryset() if not self.request.user.is_superuser: qs = qs.filter(teacher=self.request.user.teacher) return qs
|
新增一条数据时的拦截
重写save_models方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class UserCourseAdmin(object): ... list_display = ['user', 'course', 'add_time'] search_fields = ['user', 'course'] list_filter = ['user', 'course', 'add_time'] ... def save_models(self): obj = self.new_obj if not obj.id: obj.save() course = obj.course course.students += 1 course.save()
|
多个管理器管理同一张表
models.py中新建一个类,该类继承要管理的那张表
1 2 3 4 5 6 7 8
| class BannerCourse(Course): class Meta: verbose_name = "轮播课程" verbose_name_plural = verbose_name proxy = True
|
adminx.py中新建一个管理器,重写queryset方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| class BannerCourseAdmin(object): list_display = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students'] search_fields = ['name', 'desc', 'detail', 'degree', 'students'] list_filter = ['name', 'teacher__name', 'desc', 'detail', 'degree', 'learn_times', 'students'] list_editable = ["degree", "desc"]
def queryset(self): qs = super().queryset() qs = qs.filter(is_banner=True) return qs
|
注册管理类
1 2 3
| xadmin.site.register(BannerCourse, BannerCourseAdmin)
|
列表页图片字段,显示图片
自定义方法
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| class Course(BaseModel): teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE, verbose_name="讲师") course_org = models.ForeignKey(CourseOrg, null=True, blank=True, on_delete=models.CASCADE, verbose_name="课程机构") name = models.CharField(verbose_name="课程名", max_length=50) desc = models.CharField(verbose_name="课程描述", max_length=300) learn_times = models.IntegerField(default=0, verbose_name="学习时长(分钟数)") degree = models.CharField(verbose_name="难度", choices=(("cj", "初级"), ("zj", "中级"), ("gj", "高级")), max_length=2) students = models.IntegerField(default=0, verbose_name='学习人数') fav_nums = models.IntegerField(default=0, verbose_name='收藏人数') click_nums = models.IntegerField(default=0, verbose_name="点击数") notice = models.CharField(verbose_name="课程公告", max_length=300, default="") category = models.CharField(default=u"后端开发", max_length=20, verbose_name="课程类别") tag = models.CharField(default="", verbose_name="课程标签", max_length=10) youneed_know = models.CharField(default="", max_length=300, verbose_name="课程须知") teacher_tell = models.CharField(default="", max_length=300, verbose_name="老师告诉你") is_classics = models.BooleanField(default=False, verbose_name="是否经典") detail = UEditorField(verbose_name="课程详情", width=600, height=300, imagePath="courses/ueditor/images/", filePath="courses/ueditor/files/", default="") is_banner = models.BooleanField(default=False, verbose_name="是否广告位") image = models.ImageField(upload_to="courses/%Y/%m", verbose_name="封面图", max_length=100)
class Meta: verbose_name = "课程信息" verbose_name_plural = verbose_name
def __str__(self): return self.name
def show_image(self): from django.utils.safestring import mark_safe return mark_safe("<img src='{}'>".format(self.image.url))
show_image.short_description = "图片" def go_to(self): from django.utils.safestring import mark_safe return mark_safe("<a href='/course/{}'>跳转</a>".format(self.id))
go_to.short_description = "跳转"
|
管理器中在list_display 添加该方法
1 2 3 4 5 6
| class NewCourseAdmin(object): ... list_display = ['name', 'desc', 'show_image', 'go_to', 'detail', 'degree', 'learn_times', 'students'] ...
|
编辑页面某些字段设置为只读
在管理器类中添加属性readonly_fields ,在该属性中添加字段
1 2 3 4 5 6
| class NewCourseAdmin(object): ... readonly_fields = ["students", "add_time"] ...
|
编辑页面隐藏某些字段
在管理器类中添加属性exclude,在该属性中添加字段
1 2 3 4 5 6 7 8
| class NewCourseAdmin(object): ... exclude= ["students", "add_time"] ...
|
用户进入列表页的默认排序
在管理器类中添加属性ordering,在该属性中添加字段
1 2 3 4 5 6
| class NewCourseAdmin(object): ... ordering = ["click_nums"] ...
|
自定义后台管理图标
1 2 3 4 5 6
| class NewCourseAdmin(object): ... model_icon = 'fa fa-addres' ...
|
自定义更多图标
百度:awesome font—> 找到中文链接—>下载,解压—>拷贝css,fonts至xadmin的原始路径下—>xadmin/static/xadmin/vendor/font-awesome
一个页面修改多个页面的信息
在adminx.py自定义一个类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class LessonInline(object): model = Lesson extra = 0 exclude = ["add_time"]
class NewCourseAdmin(object): ... inlines = [LessonInline,]
xadmin.site.register(Course, NewCourseAdmin) ...
|
集成ueditor富文本编辑器到xadmin中
注:由于Ueditor富文本不在维护,本文仅以学习为主。将下载好的Ueditor依赖拉入site-package或拖入项目中。
github地址:https://github.com/zhangfisher/DjangoUeditor
配置
settings.py
1 2 3 4 5 6 7
| 在INSTALL_APPS里面增加DjangoUeditor app,如下: INSTALLED_APPS = ( 'DjangoUeditor', )
|
urls.py
1 2 3
| url(r'^ueditor/',include('DjangoUeditor.urls' )),
|
在model中的使用
1 2 3 4 5 6 7
| from DjangoUeditor.models import UEditorField class Blog(models.Model): Name=models.CharField(,max_length=100,blank=True) Content=UEditorField('内容 ',width=600, height=300, toolbars="full", imagePath="", filePath="", upload_settings={"imageMaxSize":1204000}, settings={},command=None,event_handler=myEventHander(),blank=True)
|
集成xadmin
xadmin的plugins创建一个ueditor.py
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 29 30 31 32 33 34 35 36 37
|
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)
|
在xadmin的plugins中的init.py注册ueditor插件
1 2 3 4 5 6 7 8 9 10 11 12
| PLUGINS = ( 'actions', 'filters', 'bookmark', 'layout', 'refresh', ... 'ueditor', )
|
urls.py
1 2 3 4 5 6 7
| class NewCourseAdmin(object): style_fields = { "detail": "ueditor" }
|
在templates中可能要使用:
{ % autoescape off %}…{ % endautoescape % }:关闭django转义
xadmin数据的导入和导出
依赖
1 2
| pip install django-import-export
|
注册app
1 2 3 4 5 6 7
| INSTALLED_APPS = [ …
‘import_export’, … ]
|
使用
1 2 3 4 5 6 7 8 9 10 11 12 13
| class MyResource(resources.ModelResource): class Meta: model = Course
class NewCourseAdmin(object): ... import_export_args = {'import_resource_class': MyResource, 'export_resource_class': MyResource} ...
|
如果要去掉自带的导出功能,到xadmin下的 plugins的__init__注释掉export