第三百九十六节,Django+Xadmin打造上线标准的在线教育平台—其他插件使用说,自定义列表页上传插件

设置后台列表页面字段统计

在当前APP里的adminx.py文件里的数据表管理器里设置

aggregate_fields = {'字段名称':'sum为统计数,min为统计时间'}

class CourseAdmin(object):               # 自定义数据表管理器类

    # 设置xadmin后台显示字段
list_display = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students',
'fav_nums', 'image', 'click_nums', 'add_time'] # 设置xadmin后台搜索字段,注意:搜索字段如果有时间类型会报错
search_fields = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students',
'fav_nums', 'image', 'click_nums'] # 设置xadmin后台过滤器帅选字段,时间用过滤器来做
list_filter = ['name', 'desc', 'detail', 'degree', 'learn_times', 'students',
'fav_nums', 'image', 'click_nums', 'add_time']
model_icon = 'fa fa-clone'
style_fields = {'detail':'ueditor'}
# import_excel = True
aggregate_fields = {'fav_nums':'sum'} xadmin.site.register(Course, CourseAdmin) # 将数据表注册到xadmin后台显示

自定义列表页上传插件

注册插件APP

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app_users', # 注册 APP
'app_courses',
'app_organization',
'app_operation',
'xadmin', # 注册xadmin的app
'reversion',
'crispy_forms', # 注册xadmin的依赖app
'captcha', # 注册验证码app
'pure_pagination', # 注册分页app
'DjangoUeditor', # 注册DjangoUeditor的APP
'wen_jian_shang_chuanpy', # 注册上传插件app
]

配置插件上传URL路由逻辑

from extra_apps.wen_jian_shang_chuanpy.shang_chuan_wen_jian import Shang_chuan_wen_jian
urlpatterns = [
url(r'^xadmin/', xadmin.site.urls), url(r'^index.html', TemplateView.as_view(template_name='index.html'), name='index'), # 注册
url(r'^register.html', zhu_ce.as_view(), name='register'),
url(r'^captcha/', include('captcha.urls'), name='captcha'),
url(r'^active/(?P<active_de>.*)/$', active_code.as_view(), name="user_active"), # 登录
url(r'^login.html', TemplateView.as_view(template_name='login.html'), name='login'),
url(r'^deng_lu', deng_lu.as_view(), name='deng_lu'),
url(r'^logout', logout.as_view(), name='deng_lu'), # 授课机构
url(r'^org_list.html', org_list.as_view(), name='org_list'), # 专门处理静态资源请求映射,也就是media上传文件夹里的请求映射
url(r'media/(?P<path>.*)$', serve, {'document_root': MEDIA_ROOT}), # 配置静态文件访问
# url(r'static/(?P<path>.*)$', serve, {'document_root': STATIC_ROOT}), url(r'course_comment.html', course_comment.as_view(), name='course_comment'),
url(r'usercenter_info.html', usercenter_info.as_view(), name='usercenter_info'), # 上传头像
url(r'touxiang/', touxiang.as_view(), name='touxiang'), # 配置DjangoUeditor富文本路由映射
url(r'^ueditor/', include('DjangoUeditor.urls')), # 配置后台上传映射
url(r'^shang_chuan_wen_jian/', Shang_chuan_wen_jian, name='Shang_chuan_wen_jian'),
]

models.py里要上传文件的类里自定义函数,函数里执行插件里的一个函数

class CourseResource(models.Model):
course = models.ForeignKey(Course, verbose_name='外键课程表')
name = models.CharField(max_length=100, verbose_name='课程资源名称')
download = models.FileField(upload_to='course/resource/%Y/%m', storage=ImageStorage(), verbose_name='资源文件', max_length=100)
add_time = models.DateTimeField(default=datetime.now, verbose_name='添加日期') class Meta:
verbose_name = '课程资源表'
verbose_name_plural = verbose_name # 自定义列 def xiougai(self):
from extra_apps.wen_jian_shang_chuanpy.shang_chuan_wen_jian import book_hanshu
book = book_hanshu(self.download, self.id, 'app_courses', 'CourseResource', 'download')
return book # 返回HTML显示到页面
xiougai.short_description = '修改文件' def __str__(self):
return self.name

adminx.py里开启插件

class CourseResourceAdmin(object):
list_display = ['course', 'name', 'download', 'add_time', 'xiougai']
search_fields = ['course', 'name', 'download']
list_filter = ['course', 'name', 'download', 'add_time']
model_icon = 'fa fa-hdd-o'
# list_editable = ['download']
# show_detail_fields = ['download']
shang_chuan_wen_jian = True xadmin.site.register(CourseResource, CourseResourceAdmin)

插件文件shang_chuan_wen_jian.py

#!/usr/bin/env python
# -*- coding:utf8 -*-
import json
from django.shortcuts import render, HttpResponse, redirect
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.safestring import mark_safe # 允许执行html代码 from xadmin.sites import site
from xadmin.views import BaseAdminPlugin, ListAdminView, CommAdminView, ModelAdminView from MxOnline import settings
from apps.utils.uploadfile import Uploadfile def book_hanshu(download, id, app, models_biao, ziduan):
"""
:第一个参数,接收上传数据字段的数据库数据
:第二个参数,接收上传数据字段的数据库数据id
:第三个参数,接收当前的APP名称
:第四个参数,接收当前数据表的类名
:第五个参数,接收,当前上传字段名称
:return:
"""
book = """
<div class="modal fade" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span>&times;</span></button>
<h4 class="modal-title">上传文件</h4></div>
<div class="modal-body">
<form method="post" enctype="multipart/form-data">
<div id="yuan_shi" class="alert alert-success"></div>
<div id="tishi" class="alert alert-success">请选择您要上传的文件</div>
<input id="file" class="btn btn-default" type="file" name="file"/>
<input id='app' value="" type="hidden" name="app"/>
<input id='models_biao' value="" type="hidden" name="models_biao"/>
<input id='n_id' value="" type="hidden" name="n_id"/>
<input id='ziduan' value="" type="hidden" name="ziduan"/>
<span id="daxiao"></span><br/>
<span id="daxiao2"></span><br/>
<div id="jdt" class="progress">
<div id="prog" class="progress-bar" style="min-width:20px; width: 0%;">0%</div>
</div>
</form>
</div>
<div class="modal-footer">
<button id="shch_anllou" type="button" class="btn btn-primary">
上传文件
</button>
</div>
</div>
</div>
</div>
<!--data-toggle="modal"声明事件切换类型,modal表示模态框类型(Bootstrap)-->
<!--data-target="#myModal">声明事件操作对象,#myModal表示点击后关闭id为#myModal的元素(Bootstrap)-->
<span></span>
<button n_nr="{download}" n_id='{n_id}' app='{app}' models_biao='{models_biao}' ziduan='{ziduan}' class="btn btn-primary btn-xs xiou_gai" data-toggle="modal" data-target="#myModal">
点击修改
</button>
""".format(download=download, n_id=id, app=app, models_biao=models_biao, ziduan=ziduan)
return mark_safe(book) # 上传逻辑
@csrf_exempt
def Shang_chuan_wen_jian(request):
if request.method == "POST":
file = request.FILES.get('file') # 获取上传文件对象
xieru_wjian = Uploadfile('course/resource',file) app = request.POST.get('app') # 获取前台传过来的APP名称
models_biao = request.POST.get('models_biao') # 获取前台传过来的数据表名称
n_id = request.POST.get('n_id') # 获取前台传过来的数据id
ziduan = request.POST.get('ziduan') # 获取要修改的字段 # 动态导入数据库模块
orm = __import__('{0}.models'.format(app),models_biao,fromlist=True)
pd_models_biao = hasattr(orm,models_biao) # 判断当前数据表是否存在
if pd_models_biao and xieru_wjian:
hq_models_biao = getattr(orm,models_biao) # 如果存在,找到数据表类
xieru = {ziduan:xieru_wjian}
biao = hq_models_biao.objects.filter(id=n_id).update(**xieru)
if biao:
return HttpResponse(json.dumps({'url':xieru_wjian}))
else:
return HttpResponse('数据表不存在') return HttpResponse('') class EditablePlugin(BaseAdminPlugin):
shang_chuan_wen_jian = False def init_request(self, *args, **kwargs):
return bool(self.shang_chuan_wen_jian) # 在网页头部注入js[列表页,内容页]
def block_extrahead(self, context, nodes):
js = '<script type="text/javascript" src="{0}"></script>'.format(settings.STATIC_URL + 'shang_chuan_wen_jian.js')
# js += '<script type="text/javascript" src="{0}"></script>'.format(settings.STATIC_URL + 'jquery.form.js')
nodes.append(js) site.register_plugin(EditablePlugin, ListAdminView) # 列表逻辑

js文件

/**
* Created by admin on 2017/9/26.
*/
jQuery(function ($) { var totalSize = 0; //初始化隐藏进度条
$('#jdt').hide(); //绑定所有type=file的元素的onchange事件的处理函数
//当选定文件时触发函数
$(':file').change(function () {
var file = this.files[0]; //假设file标签没打开multiple属性,那么只取第一个文件就行了
name = file.name;
size = file.size;
type = file.type;
url = window.URL.createObjectURL(file); //获取本地文件的url,如果是图片文件,可用于预览图片 //$(this).next().html("文件名:" + name + " 文件类型:" + type + " 文件大小:" + size + " url: " + url); totalSize += size;//字节
var mb = parseInt(totalSize / 1024 / 1024);
$("#daxiao").html("总大小: " + totalSize + "-字节");
$("#daxiao2").html("总大小: " + mb + "-mb"); }); //点击修改按钮时触发函数
$('.xiou_gai').click(function () {
//获取需要传递到后台的参数
var n_nr = $(this).attr('n_nr');
var n_id = $(this).attr('n_id');
var app = $(this).attr('app');
var models_biao = $(this).attr('models_biao');
var ziduan = $(this).attr('ziduan');
//将参数填充到表单以便提交后台
$('#yuan_shi').text('原始文件:' + n_nr);
$('#n_id').val(n_id);
$('#app').val(app);
$('#models_biao').val(models_biao);
$('#ziduan').val(ziduan);
}); //向表单区域添加一个form标签
$('#myModal').wrap('<form id="form" method="post" enctype="multipart/form-data">');
$('#form').wrap('<div id="form_zhuti">'); //点击上传按钮后触发函数
$('#shch_anllou').click(function () {
var file_zhi = $('#file').val();
if (file_zhi){
upload()
}else {
$('#tishi').attr('class','alert alert-danger')
} }); //点击选择框后恢复提示框颜色
$('#file').click(function () {
$('#tishi').attr('class','alert alert-success');
$('#tishi').text('请选择您要上传的文件')
}); //ajax提交函数
function upload() {
//创建FormData对象,初始化为form表单中的数据。需要添加其他数据可使用formData.append("property", "value");
var formData = new FormData($('#form_zhuti form')[0]);
$('#jdt').show();
$.ajax({
url: "/shang_chuan_wen_jian/",
type: "POST",
data: formData,
dataType: 'json',
//获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
xhr: function () {
myXhr = $.ajaxSettings.xhr();
//检查upload属性是否存在
if (myXhr.upload) {
//绑定progress事件的回调函数
myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
}
return myXhr; //xhr对象返回给jQuery使用
},
success: function (result) {
//返回json格式,里面是上传成功后的URL
// alert(result.url);
$('#yuan_shi').text(result.url);
$('#tishi').text('恭喜上传成功!');
$('#tishi').attr('class','alert alert-info');
$('#tishi').attr({'style':'font-size:20px;font-weight:bold;'}); //睡眠
setTimeout(function () {
// window.location.reload(); //刷新浏览器
top.location.reload(); //刷新页面
}, 2000); },
contentType: false, //必须false才会自动加上正确的Content-Type
processData: false, //必须false才会避开jQuery对 formdata 的默认处理
error:function (xhr, status, info){
$('#tishi').attr('class','alert alert-danger');
$('#tishi').text('遗憾上传出错了')
}
});
} //上传进度回调函数:
function progressHandlingFunction(e) {
if (e.lengthComputable) {
var percent = e.loaded / e.total * 100;
var bfbi = percent.toFixed(2) + "%";
$('#prog').attr("style", 'width:' + bfbi); //更新数据到进度条
$('#prog').html(bfbi);
// $('#daxiao3').html(e.loaded + "/" + e.total+" bytes. " + percent.toFixed(2) + "%");
}
} //当上传框关闭后触发
$('#myModal').on('hide.bs.modal', function () {
//当模态框关闭是清空表单和参数
$('#yuan_shi').text('');
$('#n_id').val('');
$('#app').val('');
$('#models_biao').val('');
$('#file').val('');
$('#daxiao').text('');
$('#daxiao2').text('');
$('#jdt').hide();
$('#prog').attr("style", {'width': 0}); //更新数据到进度条
$('#prog').html(0);
$('#tishi').attr('class','alert alert-success');
$('#ziduan').val('');
}); });

最终效果

补充:adminx.py 注册管理器,接收每次后台提交的请求,进行逻辑处理

# 录音作品
class app_zuopinAdmin(object): # 设置xadmin后台显示字段
list_display = ['id', 'title', 'psrc', 'lu_yin_shang_chuan', 'yangsrc', 'yamg_yin_shit', 'shen_chen_yang_yin'] # 设置xadmin后台搜索字段,注意:搜索字段如果有时间类型会报错
search_fields = ['id', 'title', 'des', 'key', 'psrc'] # # 设置xadmin后台过滤器帅选字段,时间用过滤器来做
list_filter = ['title', 'des', 'key', 'xing_bie', 'yu_zhong', 'ti_cai', 'shi_jian'] def post(self, request, *args, **kwargs): 逻辑处理 # 一定要这样返回,否则会出错
return super(app_zuopinAdmin, self).post(request, *args, **kwargs) # 管理器重写后重新注册
xadmin.site.register(Zuopin, app_zuopinAdmin)

第三百九十六节,Django+Xadmin打造上线标准的在线教育平台—其他插件使用说,自定义列表页上传插件的更多相关文章

  1. 第三百九十八节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5系统环境设置

    第三百九十八节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5系统环境设置 1.Linux安装配置 注意事项: 虚拟机网卡桥接模式 不要拨VPN 如果,网络怎么都 ...

  2. 第三百九十三节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置

    第三百九十三节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置 设置后台某个字段的排序规则 在当前APP里的adminx.py文件里的数据表管理器里设置 order ...

  3. 第三百九十二节,Django+Xadmin打造上线标准的在线教育平台—sql注入攻击,xss攻击,csrf攻击

    第三百九十二节,Django+Xadmin打造上线标准的在线教育平台—sql注入攻击,xss攻击,csrf攻击 sql注入攻击 也就是黑客通过表单提交的地方,在表单里输入了sql语句,就是通过SQL语 ...

  4. 第三百八十二节,Django+Xadmin打造上线标准的在线教育平台—xadmin管理员详情页面布局,导航图标设置

    第三百八十二节,Django+Xadmin打造上线标准的在线教育平台—xadmin进阶 1.后台管理员详情页面布局 后台管理员详情页面,区块是可以拖动的,而且分为了很多个区块 这个页面的布局在xadm ...

  5. 第三百九十九节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5安装mysql5.6

    第三百九十九节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5安装mysql5.6 1.检测系统是否已经安装过mysql或其依赖,若已装过要先将其删除,否则第4步 ...

  6. 第三百九十五节,Django+Xadmin打造上线标准的在线教育平台—Xadmin集成富文本框

    第三百九十五节,Django+Xadmin打造上线标准的在线教育平台—Xadmin集成富文本框 首先安装DjangoUeditor3模块 Ueditor HTML编辑器是百度开源的HTML编辑器 下载 ...

  7. 第三百九十四节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置2,以及目录结构说明

    第三百九十四节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置2,以及目录结构说明 设置后台列表页面可以直接修改字段内容 在当前APP里的adminx.py文件里的 ...

  8. 第三百九十节,Django+Xadmin打造上线标准的在线教育平台—Django+cropper插件头像裁剪上传

    第三百九十节,Django+Xadmin打造上线标准的在线教育平台—Django+cropper插件头像裁剪上传 实现原理 前台用cropper插件,将用户上传头像时裁剪图片的坐标和图片,传到逻辑处理 ...

  9. 第三百八十六节,Django+Xadmin打造上线标准的在线教育平台—HTML母版继承

    第三百八十六节,Django+Xadmin打造上线标准的在线教育平台—HTML母版继承 母板-子板-母板继承 母板继承就是访问的页面继承一个母板,将访问页面的内容引入到母板里指定的地方,组合成一个新页 ...

随机推荐

  1. 解决iframe重复嵌套登陆页面的问题

    在login.jsp中加入即可 // 在被嵌套时就刷新上级窗口 if(window.parent != window){ window.parent.location.reload(true); }

  2. Python 线程和进程和协程总结

    Python 线程和进程和协程总结 线程和进程和协程 进程 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间.内存等)的基本单位: 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其 ...

  3. 转载一篇关于toString和valueOf

    可以这样说,所有JS数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题.在程序应用非常广泛.下面我们逐一来给大家介绍下. Java ...

  4. Golang 实现 set 集合,变相实现 切片去重、排序 功能

    Java 中的集合(set)去重很方便,PHP 中的数组值去重,就更加方便,一个函数搞定:array_unique(),Golang 中就比较苦逼了,官方没有提供对“切片去重”的功能,而项目中,又经常 ...

  5. ASP.NET Web API实现缓存的2种方式

    在ASP.NET Web API中实现缓存大致有2种思路.一种是通过ETag, 一种是通过类似ASP.NET MVC中的OutputCache. 通过ETag实现缓存 首先安装cachecow.ser ...

  6. java 线程池 使用实例

    在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统 ...

  7. Spring boot 远程调试

    设置远程调试,可以在正式环境上随时跟踪与调试生产故障. 依赖 在 pom.xml 中增加远程调试依赖(试了下,不加也行). <plugins> <plugin> <gro ...

  8. 使用sshfs挂载远程服务器目录

    点击访问原文 您还可以加入全栈技术交流群(QQ群号:254842154) 服务器日志查看,是开发人员和服务器运维人员在工作中经常会遇到的一件事情,只有一台服务器时,比较好办,直接登录服务器使用tail ...

  9. SpringBoot(八):系统错误统一拦截器

    在日常 web 开发中发生了异常,往往需要通过一个统一的 异常处理,来保证客户端能够收到友好的提示.本文将会介绍 Spring Boot 中的 全局统一异常处理. Springboot的全局异常查是通 ...

  10. MDX Cookbook 01 - Skipping Axis 合理使用空的 SET 集合获取全部层次结构成员

    假设我们只想显示一些与数据没有任何关联的维度成员信息,并且希望它们能够以行集的形式来显示,那么在 MDX 中就应该直接显示 ROWS  AXIS (1) 并且忽略掉 COLUMNS AXIS(0).比 ...