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)