参考: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插件开发的更多相关文章

  1. django 线上教育平台开发记录

    1.环境搭建 2.新建项目 1).首先通过 django-admin 新建一个项目,(例如项目名为mxonline) django-admin startproject mxonline 运行后会出现 ...

  2. xadmin快速搭建后台管理系统

    一.xadmin的特点: 1.基于Bootstrap3:Xadmin使用Bootstrap3.0框架精心打造.基于Bootstrap3,Xadmin天生就支持在多种屏幕上无缝浏览,并完全支持Boots ...

  3. Django 学习之Xadmin

    一.xadmin的特点 1.基于Bootstrap3:Xadmin使用Bootstrap3.0框架精心打造.基于Bootstrap3,Xadmin天生就支持在多种屏幕上无缝浏览,并完全支持Bootst ...

  4. JavaScript学习笔记(四)——jQuery插件开发与发布

    jQuery插件就是以jQuery库为基础衍生出来的库,jQuery插件的好处是封装功能,提高了代码的复用性,加快了开发速度,现在网络上开源的jQuery插件非常多,随着版本的不停迭代越来越稳定好用, ...

  5. jira的插件开发流程实践

    怎么开头呢,由于自己比较懒,博客一直不怎么弄,以后克己一点,多传点自己遇到的问题和经历上来,供自己以后记忆,也供需要的小伙伴少走点弯路吧 最近公司项目需要竞标一个运维项目,甲方给予了既定的几种比较常用 ...

  6. Vue插件开发入门

    相对组件来说,Vue 的插件开发受到的关注要少一点.但是插件的功能是十分强大的,能够完成许多 Vue 框架本身不具备的功能. 大家一般习惯直接调用现成的插件,比如官方推荐的 vue-router.vu ...

  7. 【原创】记一次Project插件开发

    一.开发背景 最近在使用微软的Office Project 2010 进行项目管理,看到排的满满的计划任务,一个个地被执行完毕,还是很有成就感的.其实,不光是在工作中可以使用Project进行项目进度 ...

  8. JavaScript学习总结(四)——jQuery插件开发与发布

    jQuery插件就是以jQuery库为基础衍生出来的库,jQuery插件的好处是封装功能,提高了代码的复用性,加快了开发速度,现在网络上开源的jQuery插件非常多,随着版本的不停迭代越来越稳定好用, ...

  9. [Tool] Open Live Writer插件开发

    一 前言 Windows Live Writer(简称 WLW)开源之后变成 Open Live Writer(简称 OLW),原先 WLW 的插件在 OLW 下都不能用了,原因很简单,WLW 插件开 ...

随机推荐

  1. (map)水果 hdu1263

    水果 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...

  2. Qt: 文件、文件夹的操作;

    Qt没有提供单独的函数来对文件.文件夹进行操作, 但是提供了两个类: QFile, QDir; 1.文件操作 ) 文件是否存在: QFile file("D:/test.jpg") ...

  3. Uart串口

    title: Uart串口 tags: ARM date: 2018-10-20 16:38:28 --- Uart串口 和单片机的应用没什么区别,首先设置IO复用,设置波特率和数据位,以及中断相关的 ...

  4. 运维监控-Open-Falcon介绍

    运维监控-Open-Falcon介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Open-Falcon 介绍 监控系统是整个运维环节,乃至整个产品生命周期中最重要的一环,事 ...

  5. Hadoop问题:Input path does not exist: hdfs://Master:9000/user/hadoop/input

    问题描述: org.apache.hadoop.mapreduce.lib.input.InvalidInputException: Input path does not exist: hdfs:/ ...

  6. SQLyog远程连接腾讯云服务器数据库Mysql遇到的坑

    首先说明我的数据库是安装在云服务器上,不是专业的数据库服务器,没错就是10块钱包月的. 然后觉得使用SQLyog远程维护数据库比较方面,可是怎么都登录不上去. 下面分析原因: 1.安全组是否放过了访问 ...

  7. windows批量修改文件后缀名

    有时候需要批量修改一些文件的后缀名,下面介绍批量修改的方法. 1.在文件夹内新建一个.txt文本文档. 2.在文本文档内写:ren *    *.mp3 (意思是把没有后缀名的全部改成.mp3的格式, ...

  8. 【leetcode-125】 验证回文串

    给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, a plan, a c ...

  9. python-虚拟环境搭建

    虚拟环境 需求:        --公司之有一台服务器        -目前运行这一个5年前开发的Django项目,基于1.5        -现在要基于Django2.0开发一套程序         ...

  10. 子线程导致 Windows 服务停止的情况(Topshelf 结合 Quartz.NET)

    Ø  前言 本文主要记录子线程导致 Topshelf 和 Quartz.NET 的 Windows 服务停止的现象,以及使用几种常用子线程的注意事项.因为我们有时可能需要开启多个线程执行复杂的逻辑,如 ...