xadmin插件开发
参考:http://blog.csdn.net/qq_15682489/article/details/70174784
项目中新添加的organization模块需要在toolbar中添加“课表详细”,“导入”的功能,这就需要开发插件。
文件:
├── adminx.py
├── apps.py
├── __init__.py
├── models.py
├── plugins.py
└── views.py
templates目录下:
└── xadmin
├── plugins
│ ├── model_list.top_toolbar.format.html
│ └── model_list.top_toolbar.importexport.import.html
└── views
└── schedule_query.html
model_list.top_toolbar.format.html:

schedule_query.html:

model_list.top_toolbar.importexport.import.html:

plugins.py:
from json import JSONEncoder from django.template import loader
from django.template.response import TemplateResponse from utils.dataUtils import replace_html
from xadmin.views import BaseAdminPlugin
from xadmin.plugins.actions import BaseActionView
from .models import *
import json, re #显示插件
class QueryMenuPlugin(BaseAdminPlugin):
demo_query_menu = False def init_request(self, *args, **kwargs):
#指定特定页面显示插件
self.demo_query_menu = self.request.get_full_path().endswith('schedule/')
return self.demo_query_menu
#toolbar中插件显示页面
def block_top_toolbar(self, context, nodes):
if self.demo_query_menu:
nodes.append(
loader.render_to_string('xadmin/plugins/model_list.top_toolbar.format.html',
context_instance=context)
) class QueryView(BaseActionView):
def do_action(self, context):
return TemplateResponse(self.request, self.get_template_list('views/schedule_query.html'), context,
current_app=self.admin_site.name) #这个插件不需要在toolbar中显示,不需要block_top_toolbar函数,而是显示一个新的View,
class QueryPlugin(BaseAdminPlugin):
def init_request(self, *args, **kwargs):
#特定请求才显示该插件
return self.request.GET.get('q') == 'schedule' def response_action(self, ac, context):
if isinstance(ac, type) and issubclass(ac, BaseActionView):
action_view = self.get_model_view(ac, self.admin_view.model)
action_view.init_action(self.admin_view)
return action_view.do_action(context)
else:
return ac(self.admin_view, self.request, context) def get_response(self, response, context, *args, **kwargs):
teacher_id = self.request.GET.get('_p_teacher__id__exact')
clazz_id = self.request.GET.get('_p_clazz__id__exact')
schedule_list = []
select_clazz = ''
select_teacher = ''
try:
if teacher_id and clazz_id:
schedule_list = Schedule.objects.filter(teacher_id=int(teacher_id)).filter(clazz_id=int(clazz_id))
select_clazz = Class.objects.filter(id=int(clazz_id)).first()
select_teacher = Teacher.objects.filter(id=int(teacher_id)).first()
elif teacher_id:
schedule_list = Schedule.objects.filter(teacher_id=int(teacher_id))
select_teacher = Teacher.objects.filter(id=int(teacher_id)).first()
elif clazz_id:
schedule_list = Schedule.objects.filter(clazz_id=int(clazz_id))
select_clazz = Class.objects.filter(id=int(clazz_id)).first()
except:
pass session_list = Session.objects.all().order_by("start_time")
str = '['
for se in schedule_list:
str += (json.dumps(se, default=Schedule.all_schedule2json))
str += ','
str = str[0:str.__len__() - 1]
str += ']'
str = replace_html(str)
context.update({
'session_list': session_list,
'schedule_list': schedule_list,
'str': str,
'select_clazz': select_clazz,
'select_teacher': select_teacher,
})
return self.response_action(QueryView, context) # 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/plugins/model_list.top_toolbar.importexport.import.html',
context_instance=context))
model_list.top_toolbar.format.html:
{% load i18n %}
<div class="btn-group export">
<a class="btn btn-primary btn-sm" data-toggle="modal" href="?q=schedule">
<i class="fa fa-money"></i>课表详细
</a>
</div>
schedule_query.html:
{% extends base_template %}
{% load i18n l10n %}
{% load xadmin_tags %}
{% block breadcrumbs %}
<ul class="breadcrumb">
<li><a href="{% url 'xadmin:index' %}">{% trans 'Home' %}</a></li>
<li><a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a></li>
<li>课表详细</li>
</ul>
{% endblock %}
{% block content %}
<div>当前班级:{{ select_clazz }},当前讲师:{{ select_teacher }}</div>
<table class="table table-bordered table-hover table-condensed">
<thead>
<tr>
<th>节次\星期</th>
<th>星期一</th>
<th>星期二</th>
<th>星期三</th>
<th>星期四</th>
<th>星期五</th>
<th>星期六</th>
<th>星期日</th>
</tr>
</thead>
<tbody>
{% for s in session_list %}
<tr>
<td>{{ s.name }}</td>
<td data-session="第{{ forloop.counter }}节" data-week="1"></td>
<td data-session="第{{ forloop.counter }}节" data-week="2"></td>
<td data-session="第{{ forloop.counter }}节" data-week="3"></td>
<td data-session="第{{ forloop.counter }}节" data-week="4"></td>
<td data-session="第{{ forloop.counter }}节" data-week="5"></td>
<td data-session="第{{ forloop.counter }}节" data-week="6"></td>
<td data-session="第{{ forloop.counter }}节" data-week="7"></td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="form-actions well well-sm">
<form method="post" action="">{% csrf_token %}
<button class="btn btn-default"><i class="fa fa-backward"></i> 返回</button>
</form>
</div>
<script src="/static/js/jquery-1.9.1.min.js"></script>
<script>
function escape2Html(str) {
var arrEntities = {'lt': '<', 'gt': '>', 'nbsp': ' ', 'amp': '&', 'quot': '"'};
return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, function (all, t) {
return arrEntities[t];
});
}
var str = '{{ str }}';
var session_index;
var week_index;
str = escape2Html(str);
jsonObjList = JSON.parse(str);
for (var i = 0; i < jsonObjList.length; i++) {
session_index = jsonObjList[i].session
week_index = jsonObjList[i].week
if ('{{ select_clazz }}' && '{{ select_teacher }}' ){
$("td[data-session=" + session_index + "][data-week=" + week_index + "]").html(jsonObjList[i].subject+'<br>'+jsonObjList[i].classroom);
continue;
}else if('{{ select_clazz }}'){
$("td[data-session=" + session_index + "][data-week=" + week_index + "]").html(jsonObjList[i].subject+'<br>'+jsonObjList[i].teacher+'<br>'+jsonObjList[i].classroom);
continue;
}else if('{{ select_teacher }}'){
$("td[data-session=" + session_index + "][data-week=" + week_index + "]").html(jsonObjList[i].subject+'<br>'+jsonObjList[i].clazz+'<br>'+jsonObjList[i].classroom);
continue;
}
}
</script>
{% endblock %}
views.py:
from django.shortcuts import render # Create your views here.
from django.views.generic.base import View
from django.http import HttpResponse, HttpResponseRedirect
from .models import *
import xlrd def import_excel(request):
excel = xlrd.open_workbook(
filename=None, file_contents=request.FILES.get('excel').read()) # 关键点在于这里
schedule_list = []
table = excel.sheets()[0]
nrows = table.nrows
ncols = table.ncols
HEAD = ['星期', '节次', '教师', '学科', '教室', '班级']
table_head = table.row_values(0)
if table_head != HEAD:
render(request, "500.html", {'msg': '数据头部错误,必须是' + "['星期', '节次', '教师', '学科', '教室', '班级']" + ",顺序不可变!"}) for i in range(nrows):
if i > 0:
schedule_list.append(table.row_values(i)) try:
insertSchedule(schedule_list)
except:
render(request, "500.html", {'msg': '部分内容不和法,请检查'}) return HttpResponseRedirect("/admin/organization/schedule/") def insertSchedule(schedule_list):
for item in schedule_list:
try:
week = item[0].strip()
session = item[1].strip()
teacher = item[2].strip()
subject = item[3].strip()
classroom = item[4].strip()
clazz = item[5].strip()
f_session = Session.objects.get(name=session)
# 需要判断同名的老师
f_teacher = Teacher.objects.get(user__username=teacher)
f_subject = Subject.objects.get(name=subject)
f_classroom = Classroom.objects.get(name=classroom)
f_clazz = Class.objects.get(name=clazz)
sc = Schedule()
sc.week = getWeek(week)
sc.session = f_session
sc.teacher = f_teacher
sc.subject = f_subject
sc.classroom = f_classroom
sc.clazz = f_clazz
sc.save()
except:
raise Exception("error") def getWeek(week):
switcher = {
"星期一": "1",
"星期二": "2",
"星期三": "3",
"星期四": "4",
"星期五": "5",
"星期六": "6",
"星期日": "7",
}
return switcher.get(week, "1")
model_list.top_toolbar.importexport.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="/admin/organization/schedule/import_excel" 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>
注册插件
xadmin:
xadmin.site.register_plugin(QueryMenuPlugin, ListAdminView)
xadmin.site.register_plugin(QueryPlugin, ListAdminView)
xadmin.site.register_plugin(ListImportExcelPlugin, ListAdminView)
xadmin插件开发的更多相关文章
- django 线上教育平台开发记录
1.环境搭建 2.新建项目 1).首先通过 django-admin 新建一个项目,(例如项目名为mxonline) django-admin startproject mxonline 运行后会出现 ...
- xadmin快速搭建后台管理系统
一.xadmin的特点: 1.基于Bootstrap3:Xadmin使用Bootstrap3.0框架精心打造.基于Bootstrap3,Xadmin天生就支持在多种屏幕上无缝浏览,并完全支持Boots ...
- Django 学习之Xadmin
一.xadmin的特点 1.基于Bootstrap3:Xadmin使用Bootstrap3.0框架精心打造.基于Bootstrap3,Xadmin天生就支持在多种屏幕上无缝浏览,并完全支持Bootst ...
- JavaScript学习笔记(四)——jQuery插件开发与发布
jQuery插件就是以jQuery库为基础衍生出来的库,jQuery插件的好处是封装功能,提高了代码的复用性,加快了开发速度,现在网络上开源的jQuery插件非常多,随着版本的不停迭代越来越稳定好用, ...
- jira的插件开发流程实践
怎么开头呢,由于自己比较懒,博客一直不怎么弄,以后克己一点,多传点自己遇到的问题和经历上来,供自己以后记忆,也供需要的小伙伴少走点弯路吧 最近公司项目需要竞标一个运维项目,甲方给予了既定的几种比较常用 ...
- Vue插件开发入门
相对组件来说,Vue 的插件开发受到的关注要少一点.但是插件的功能是十分强大的,能够完成许多 Vue 框架本身不具备的功能. 大家一般习惯直接调用现成的插件,比如官方推荐的 vue-router.vu ...
- 【原创】记一次Project插件开发
一.开发背景 最近在使用微软的Office Project 2010 进行项目管理,看到排的满满的计划任务,一个个地被执行完毕,还是很有成就感的.其实,不光是在工作中可以使用Project进行项目进度 ...
- JavaScript学习总结(四)——jQuery插件开发与发布
jQuery插件就是以jQuery库为基础衍生出来的库,jQuery插件的好处是封装功能,提高了代码的复用性,加快了开发速度,现在网络上开源的jQuery插件非常多,随着版本的不停迭代越来越稳定好用, ...
- [Tool] Open Live Writer插件开发
一 前言 Windows Live Writer(简称 WLW)开源之后变成 Open Live Writer(简称 OLW),原先 WLW 的插件在 OLW 下都不能用了,原因很简单,WLW 插件开 ...
随机推荐
- (最大连续和/最大子段和) P1115 最大子段和 洛谷
题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大. 输入输出格式 输入格式: 第一行是一个正整数NN,表示了序列的长度. 第二行包含NN个绝对值不大于1000010000的整数A_iAi ...
- -bash: /tyrone/jdk/jdk1.8.0_91/bin/java: cannot execute binary file
问题描述:今天在linux环境下安装了一下JDK,安装成功后,打算输入java -version去测试一下,结果却出错了. 错误信息:-bash: /tyrone/jdk/jdk1.8.0_91/bi ...
- python机器学习-sklearn挖掘乳腺癌细胞(三)
python机器学习-sklearn挖掘乳腺癌细胞( 博主亲自录制) 网易云观看地址 https://study.163.com/course/introduction.htm?courseId=10 ...
- Event Recommendation Engine Challenge分步解析第二步
一.请知晓 本文是基于Event Recommendation Engine Challenge分步解析第一步,需要读者先阅读上篇文章解析 二.用户相似度计算 第二步:计算用户相似度信息 由于用到:u ...
- flask blueprint
在使用flask进行一个项目编写的时候,可能会有许多个模块,如一个网站的前台(home)和后台(admin)模块,如果把这两个模块都放在一个views.py文件之中,那么最后views.py文件必然臃 ...
- 安装FreeIPA以及应用时报错汇总
安装FreeIPA以及应用时报错汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.ERROR DNS zone yinzhengjie.org.cn already exis ...
- 【SQL】SqlServer中Group By后,字符串合并
参考: 1.SQL查询语句 group by后, 字符串合并 2.sql for xml path用法 #需求: 合并列值 表结构,数据如下: id value ----- ------ aa bb ...
- Mybatis笔记二:接口式编程
目录 旧方法的弊端 接口式编程 接口式编程的好处 接口式编程的增删改查 旧方法的弊端 在Mybatis笔记一中,我们使用命名空间+id的方式实现了Mybatis的执行,不过这里的命名空间是我们随便写的 ...
- JS事件委托应用场景
给列表元素添加点击事件: 在javaScript中,添加到页面上的事件处理程序的数量,将直接关系到页面的整体运行性能. <li>标签的数量很大时,循环为每个子元素添加事件,绝非好方法. 有 ...
- DirectX11 With Windows SDK--04 使用DirectX Tool Kit帮助开发
前言(2018/11/4) DXTK库现在已经不随Github项目提供,因为只用到了其中的键鼠类,已经过提取加入到后续的项目中 但是如果你需要配置DirectXTK到自己的项目当中,可以参考这篇博客进 ...