xadmin 进阶 补充
1.xadmin字段相关
class CourseAdmin(object): '''课程''' list_display = [ 'name','desc','detail','degree','learn_times','students'] #显示的字段 search_fields = ['name', 'desc', 'detail', 'degree', 'students'] #搜索字段 list_filter = [ 'name','desc','detail','degree','learn_times','students'] #过滤字段 model_icon = 'fa fa-book' #自定义图标 ordering = ['-click_nums'] #排序功能 readonly_fields = ['click_nums'] #只读字段,不能编辑 exclude = ['fav_nums'] #不显示的字段 复制代码 inlines = [LessonInline,CourseResourceInline] #增加章节和课程资源 list_editable = ['degree','desc'] #在列表页可以直接编辑的 list_display = ['get_zj_nums'] #直接使用函数名作为字段显示 list_display = ['go_to'] # 跳转到上面定义的地址 refresh_times = [3,5] #自动刷新(里面是秒数)可选3或5秒
1.1、inline添加数据:
比如在本项目中,我们在添加课程的时候没法是没办法在同一页面下添加章节和课程资源,这时就可以用inlines去实现这一功能
class LessonInline(object): model = Lesson extra = 0 class CourseResourceInline(object): model = CourseResource extra = 0 #在CourseAdmin中使用inlines添加上面两个的方法 class CourseAdmin(object): inlines = [LessonInline,CourseResourceInline] #增加章节和课程资源
效果:在课程同一页面下,可以同时编辑章节跟课程资源
1.2、一张表分两个model管理
比如本项目中,课程分为可轮播课程跟不可轮播课程,我们可以通过表继承,将原来表分开成两个表,实现课程分类展示
1)首先,在model.py中新建BannerCourse表,继承于Course表:
class BannerCourse(Course): '''显示轮播课程''' class Meta: verbose_name = '轮播课程' verbose_name_plural = verbose_name #这里必须设置proxy=True,这样就不会再生成一张表,同时还具有Model的功能 proxy = True
2)接着,在xadmin.py文件中新建BannerCourseAdmin类,继承于object,
同时,重载父类queryset方法:
class BannerCourseAdmin(object): '''轮播课程''' list_display = [ 'name','desc','detail','degree','learn_times','students'] search_fields = ['name', 'desc', 'detail', 'degree', 'students'] list_filter = [ 'name','desc','detail','degree','learn_times','students'] model_icon = 'fa fa-book' ordering = ['-click_nums'] readonly_fields = ['click_nums'] exclude = ['fav_nums'] inlines = [LessonInline,CourseResourceInline] def queryset(self): #重载queryset方法,来过滤出我们想要的数据的 qs = super(BannerCourseAdmin, self).queryset() #只显示is_banner=True的课程 qs = qs.filter(is_banner=True) return qs
3)最后,在进行xadmin注册就可以了:
xadmin.site.register(BannerCourse, BannerCourseAdmin)
此时,课程表中是所有课程数据,轮播课程表中只有确定为要轮播的课程存在,将课程Course表重载queryset()方法,设置:
qs = qs.filter(is_banner=False),
则此时的课程表便只剩下不轮播的课程了
1.3、xadmin的其他常见功能
1)list_editable :添加此字段后,在列表页可以直接编辑数据
class CourseAdmin(object): list_editable = ['degree','desc']
2) 自定义函数作为列显示
models.py下的Course表中新增函数:
class Course(models.Model): ... ... def get_zj_nums(self): #获取课程的章节数 return self.lesson_set.all().count() get_zj_nums.short_description = '章节数' #在后台显示的中文名称
Course/xadmin中,添加函数字段:
class CourseAdmin(object): list_display = ['get_zj_nums'] #直接使用函数名作为字段显示
效果显示:
3)显示自定义的HTML代码:
- 不经过make_safe包装,代码会直接在后台某字段中显示
- 经make_safe包装,会直接渲染成HTML样式
course/modes.py:
class Course(models.Model): ... ... def go_to(self): from django.utils.safestring import mark_safe #mark_safe后就不会转义 return mark_safe("<a href='https://home.cnblogs.com/u/derek1184405959/'>跳转</a>") go_to.short_description = "跳转"
course/xadmin.py:
class CourseAdmin(object): list_display = ['go_to']
效果显示:
4)reflash.py下的定时刷新工具
course/xadmin.py:
class CourseAdmin(object): refresh_times = [3,5] #自动刷新(里面是秒数)
页面效果:
5)字段联动
应用场景:当添加一门课程的时候,希望课程机构里面的课程数 +1
这样便不用再因为新增课程,而跑去课程机构页面,将里面的课程数手动+1处理了
重写xadmin的save_models方法:
class CourseAdmin(object): ... ... def save_models(self): # 在保存课程的时候统计课程机构的课程数 # obj实际是一个course对象 obj = self.new_obj # 如果这里不保存,新增课程,统计的课程数会少一个 obj.save() # 确定课程的课程机构存在。 if obj.course_org is not None: #找到添加的课程的课程机构 course_org = obj.course_org #课程机构的课程数量等于添加课程后的数量 course_org.course_nums = Course.objects.filter(course_org=course_org).count()
2、富文本编辑器
- DjangoUeditor
- Ueditor
本节介绍DjangoUeditor
2.1、安装:
- pip install DjangoUeditor #这种安装可能会出问题
- 在GitHub上下载、解压,直接复制到我们项目目录下
下载地址:https://github.com/zhangfisher/DjangoUeditor
2.2、setting中INSTALLED_APP注册:
INSTALLED_APPS = [ 'DjangoUeditor', ]
2.3、urls.py配置:
# 富文本编辑器url path('ueditor/',include('DjangoUeditor.urls' )),
2.4、将需要改成富文本编辑的,改动如下:
class Course(models.Model): # detail = models.TextField("课程详情") detail = UEditorField(verbose_name=u'课程详情', width=600, height=300, imagePath="courses/ueditor/", filePath="courses/ueditor/", default='')
2.5、需要在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 # 在我们生成的页面中放入自己的js文件 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)
2.6、xadmin包下的plugins/__init__.py 中添加ueditor:
PLUGINS = ( 'ueditor', )
2.7、相关app注册xadmin时,添加字段:
style_fields = {"detail": "ueditor"},如:
# course/adminx.py class CourseAdmin(object): #detail就是要显示为富文本的字段名 style_fields = {"detail": "ueditor"}
2.8、富文本编辑出来的文本,在后台显示是以html格式的形式,但当展现到前端时会被转义,无法渲染成html代码,此时需要使用:
{% autoescape off %}{% endautoescape %} ,作用是用于关闭django前端模板渲染时自动转义的功能,即停止对包裹其中的代码块进行转义
# course_detail.html
<div class="tab_cont tab_cont1"> {% autoescape off %} {{ course.detail }} {% endautoescape %} </div>
2.9、报错:
如果报错:TypeError: 'NoneType' object is not reversible
原因:django2.0中的python3.6/site-packages/django/forms/widgets.py 文件的地114行中reversed()函数中的参数list_2值为None时就会报错
解决方法:在widgets.py的文件的114行 for path in reversed(list_2): 之前添加一个判断list_2的None情况,为None赋值 list_2 = [] ,如下:
if list_2 is None: list_2 = []
解决了应该就没问题了。