Django+Xadmin打造在线教育系统(九)
xadmin的进阶开发
因版本问题.有些配置可能无效
自定义icon
xadmin的图标采用的是第三方css样式font awesome
,我们可以进官网下载最新的样式替代原本的,下载地址:http://www.fontawesome.com.cn/
下载完后把里面的“css”和“fonts”两个文件夹拷贝到xadmin的源码(路径:xadmin/static/vendor/font-awesome
)里面
使用model_icon
来进行修改
# Course的admin管理器
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'
默认排序、只读字段和不显示的字段
课程:
- 按点击数倒序排序
- 点击数不能编辑
- 不显示收藏人数
# Course的admin管理器
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'] #不显示的字段
下拉框搜索
写在外键所指的adminx配置中
relfield_style = 'fk-ajax'
当有外键指向他,会以ajax方式加载
数据量过大时很有用
inlines添加数据
目前在添加课程的时候没法添加章节和课程资源,我们可以用inlines去实现这一功能
class LessonInline(object):
model = Lesson
extra = 0
class CourseResourceInline(object):
model = CourseResource
extra = 0
# 在CourseAdmin中使用inlines添加上面两个的方法
class CourseAdmin(object):
inlines = [LessonInline,CourseResourceInline] #增加章节和课程资源
一张表分两个Model来管理
课程里面分为轮播课程和不是轮播课程两种类型,我们可以分开来管理
在course/models.py
里面新建一个Model
class BannerCourse(Course):
'''显示轮播课程'''
class Meta:
verbose_name = '轮播课程'
verbose_name_plural = verbose_name
#这里必须设置proxy=True,这样就不会再生成一张表,同时还具有Model的功能
proxy = True
course/adminx.py
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] #增加章节和课程资源
def queryset(self):
# 重载queryset方法,来过滤出我们想要的数据的
qs = super(CourseAdmin, self).queryset()
# 只显示is_banner=True的课程
qs = qs.filter(is_banner=False)
return qs
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
# 将管理器与model进行注册关联
xadmin.site.register(Course, CourseAdmin)
xadmin.site.register(BannerCourse, BannerCourseAdmin)
xadmin的其它常见功能
可以在列表上快速修改内容
list_editable = [ 'degree','desc']
自定义函数作为列
def get_zj_nums(self):
return self.lesson_set.all().count()
get_zj_nums.short_description = "章节数"
显示自定义的html代码
def go_to(self):
from django.utils.safestring import mark_safe
# 如果不mark safe。会对其进行转义
return mark_safe("<a href='http://iceflower.xyz'>跳转</>")
go_to.short_description = "跳转"
refresh定时刷新工具
refresh_times = [3,5] #自动刷新(里面是秒数)
字段联动
应用场景:当添加一门课程的时候,希望课程机构里面的课程数 +1
重写xadmin的save_models方法
def save_models(self):
# 在保存课程的时候统计课程机构的课程数
# 字段联动
obj = self.new_obj
# 新增课程还没有保存,统计的课程数少一个
obj.save()
# 必须确定存在。
if obj.course_org is not None:
# obj实际是一个course对象
course_org = obj.course_org
course_org.course_nums = Course.objects.filter(course_org = course_org).count()
course_org.save()
xadmin自行探究
- local 语言包
- migration 数据表的记录
- plugins 每一个后台页面都是一个plugin 插件机制
- static文件。js css
- template xadmin自己用到的html文件
- 对django admin的封装
增加富文本编辑器Ueditor
下载地址 https://github.com/twz915/DjangoUeditor3/
解压后,把DjangoUeditor文件夹拷贝到项目目录下面
# settings中添加app
INSTALLED_APPS = [
'DjangoUeditor',
]
# 富文本编辑器url
path('ueditor/',include('DjangoUeditor.urls' )),
course/models.py
中Course修改detail字段
class Course(models.Model):
# detail = models.TextField("课程详情")
detail = UEditorField(verbose_name=u'课程详情', width=600, height=300, imagePath="courses/ueditor/",
filePath="courses/ueditor/", default='')
xadmin/plugs
目录下新建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)
xadmin/plugs/__init__.py
里面添加ueditor插件
PLUGINS = (
'ueditor',
)
course/adminx.py
中使用
class CourseAdmin(object):
#detail就是要显示为富文本的字段名
style_fields = {"detail": "ueditor"}
在模板中必须关闭Django的自动转义才能正常显示
<div class="tab_cont tab_cont1">
{% autoescape off %}
{{ course.detail }}
{% endautoescape %}
</div>
或者
{{ course.detail|safe }}
导入excel
- 如何注入导入excel代码到菜单
- 如何只在课程列表显示
- 如何接收文件对文件进行处理
新建xadmin/plugins/excel.py
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):
nodes.append(loader.render_to_string('xadmin/excel/model_list.top_toolbar.import.html', context=get_context_dict(context)))
xadmin.site.register_plugin(ListImportExcelPlugin, ListAdminView)
添加到__init__.py文件中
PLUGINS = (
'excel',
)
新建xadmin/templates/xadmin/excel/model_list.top_toolbar.import.html
{% load i18n %}
<div class="btn-group export">
<a class="dropdown-toggle btn btn-default btn-sm" data-toggle="dropdown" href="#">
<i class="icon-share"></i> 导入 <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li><a data-toggle="modal" data-target="#export-modal-import-excel"><i class="icon-circle-arrow-down"></i> 导入 Excel</a></li>
</ul>
<script>
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;
}
}
}
</script>
<div id="export-modal-import-excel" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">导入 Excel</h4>
</div>
<div class="modal-body">
<input type="file" onchange="fileChange(this)" name="excel" id="submit_upload">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
<button class="btn btn-success" type="submit" id="submit_upload_b"><i class="icon-share"></i> 导入</button>
</div>
</form>
</div><!-- /.modal-content -->
</div><!-- /.modal-dalog -->
</div><!-- /.modal -->
</div>
只需要在adminx中设置变量import_excel=True
就可以开启导入按钮
在adminx中重写post
方法,将文件内容保存到数据中
def post(self, request, *args , **kwargs):
if 'excel' in request.FILES:
pass
# 中间pass步骤不管做什么事情,都要最后return父类的
return super(CourseAdmin, self).post(request, args, kwargs)
Django+Xadmin打造在线教育系统(九)的更多相关文章
- Django+Xadmin打造在线教育系统(四)
完成授课机构的功能 模板继承 在templates目录下,新建base.html,剪切org-list.html内容到里面 编写org-list.html内容 继承base.html,将里面的面包屑和 ...
- Django+Xadmin打造在线教育系统(三)
完成登录 注册 找回密码 激活 验证码集成 将HTML文件拷贝到templates目录下,css,js,img,media,images文件夹拷贝到static文件夹下 修改index.html和lo ...
- Django+Xadmin打造在线教育系统(二)
基于xadmin的后台管理 先使用pip进行安装xadmin及其依赖包 pip install django-adminx 安装完成后卸载xadmin,保留依赖包即可 pip uninstall dj ...
- Django+Xadmin打造在线教育系统(七)
全局导航&个人中心&全局搜索 配置全局导航 让index页面也继承base页面,注意首页有个单独的__index.js__ base页面的导航栏也进行配置 <nav> &l ...
- Django+Xadmin打造在线教育系统(一)
系统概括: 系统具有完整的用户登录注册以及找回密码功能,拥有完整个人中心. 个人中心: 修改头像,修改密码,修改邮箱,可以看到我的课程以及我的收藏.可以删除收藏,我的消息. 导航栏: 公开课,授课讲师 ...
- Django+Xadmin打造在线教育系统(八)
首页和全局404,500配置 轮播图 公开课 授课机构 新建view ## 首页view class IndexView(View): def get(self,request): # 取出轮播图 a ...
- Django+Xadmin打造在线教育系统(五)
课程相关功能实现 课程列表 创建课程相关的urls.py path("course/", include('course.urls', namespace="course ...
- Django+Xadmin打造在线教育系统(六)
讲师相关功能实现 拷贝并修改teacher-list.html和teacher-detail.html, 继承base模板 # 讲师列表 path('teacher_list/', TeacherLi ...
- Django+xadmin打造在线教育平台(一)
目录 在线教育平台(一) 在线教育平台(二) 在线教育平台(三) 在线教育平台(四) 在线教育平台(五) 在线教育平台(六) 在线教育平台(七) 在线教育平台( ...
随机推荐
- [书籍]重温《Framework Design Guidelines》
1. 前言 最近重温了<Framework Design Guidelines>. <Framework Design Guidelines>中文名称为<.NET设计规范 ...
- wtf_1234
好无聊啊,今天困的厉害. 不想做任何事情 wtf bitch!
- Spring基于AspectJ的AOP的开发——注解
源码:https://gitee.com/kszsa/dchart 一, AspectJ的概述: AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法所以它有一个专 ...
- python第五章:文件--小白博客
文件操作, 操作文件完毕后一定要记得close # 读,默认是rt(文本的方式读取),rb模式是以字节读取 # 文件路径可以用3中形式表示 f = open(r'C:\Users\fengzi\Des ...
- POJ - 2528 区间离散化,线段树区间修改,区间询问
这个题非常有意思的地方是,我们发现区间[1,4]和[5,8]是紧挨着的,因为这个的数代表的是一段区间,原本我们对于普通的离散, a[1]=1,a[2]=5,a[3]=6,a[4]=8;数组下标就是重新 ...
- Python学习第二篇
list_num=list(range(1,1000001)) print(min(list_num)) print(max(list_num)) print(sum(list_num)) print ...
- Beta阶段冲刺汇总(团队)
写在前面 汇总成绩排名链接 1.作业链接 第十一次作业--项目Beta冲刺(团队) 2.评分准则 本次作业包括现场Beta答辩评分(映射总分为100分)+博客分(总分120分)+贡献度得分,其中博客分 ...
- MySQL 使用左连接替换not in
众所周知,左连接和右连接的含义是以哪一张表为准. 左连接就是以左表为准,查出的结果中包含左表所有的记录,如果右表中没有与其对应的记录,那么那一行记录中B表部分的内容就全是NULL. 现在有两个表,一个 ...
- Oracle如何扩展表空间
一: --查看表空间的名字及文件所在位置 select tablespace_name, file_id, file_name, ), ) total_space from sys.dba_data_ ...
- [转帖]Linux 硬件和系统配置查看命令小结
https://blog.csdn.net/strongwangjiawei/article/details/8208825 转帖了不少 发现自己记住的还是不多.. Linux 硬件和系统配置查看命令 ...