From 151fcaacb561d6bfe4110fda1cd8a2a66ecfe0a8 Mon Sep 17 00:00:00 2001 From: raiots Date: Sat, 27 Mar 2021 21:35:41 +0800 Subject: [PATCH] add: import-export --- TasksManager/settings.py | 3 + apps/tasks/admin.py | 179 ++++++++++++++++++++++++++++++++++++++- apps/tasks/resources.py | 13 +++ apps/tasks/views.py | 2 +- apps/users/admin.py | 30 ++++++- requirements.txt | 13 ++- 6 files changed, 233 insertions(+), 7 deletions(-) create mode 100644 apps/tasks/resources.py diff --git a/TasksManager/settings.py b/TasksManager/settings.py index 2e4f515..7a18373 100644 --- a/TasksManager/settings.py +++ b/TasksManager/settings.py @@ -39,6 +39,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'import_export', 'apps.users', 'apps.tasks', ] @@ -135,6 +136,8 @@ LOGIN_REDIRECT_URL = '/' # 自定义用户模型 AUTH_USER_MODEL = 'users.User' +# 它确定库是否会在数据导入中使用数据库事务,以确保安全。 +IMPORT_EXPORT_USE_TRANSACTIONS = True # SimpleUI 配置 diff --git a/apps/tasks/admin.py b/apps/tasks/admin.py index 9810b7b..8733816 100644 --- a/apps/tasks/admin.py +++ b/apps/tasks/admin.py @@ -1,10 +1,14 @@ import re from django.contrib import admin +from django.http import JsonResponse from django.utils.html import format_html +from import_export.admin import ImportExportModelAdmin +from import_export.formats import base_formats from . import models from apps.users.models import TaskProperty, User +from .resources import TodoResources, TaskResources class TodoInline(admin.StackedInline): @@ -26,7 +30,8 @@ class TodoInline(admin.StackedInline): # classes = ['collapse'] -class TaskAdmin(admin.ModelAdmin): +class TaskAdmin(ImportExportModelAdmin): + resource_class = TaskResources # def formfield_for_manytomany(self, db_field, request, **kwargs): # if db_field.name == "related_task": @@ -76,8 +81,23 @@ class TaskAdmin(admin.ModelAdmin): # autocomplete_fields = ('related_task',) # search_fields = ('related_task',) + # 导入导出功能限制 + def get_export_formats(self): # 该方法是限制格式为XLS + formats = ( + base_formats.XLS, + ) + return [f for f in formats if f().can_export()] -class TodoAdmin(admin.ModelAdmin): + def has_import_permission(self, request): # 这是隐藏导入按钮,如果隐藏其他按钮也可以这样操作, + if request.user.is_superuser: + return True + else: + return False + + +# class TodoAdmin(admin.ModelAdmin): +class TodoAdmin(ImportExportModelAdmin): + resource_class = TodoResources # 工作包页面仅显示所属本部门的年度任务、承办人、协办人 def formfield_for_foreignkey(self, db_field, request, **kwargs): @@ -133,7 +153,7 @@ class TodoAdmin(admin.ModelAdmin): list_filter = ('deadline',) list_display_links = ('todo_topic', 'deadline', ) date_hierarchy = 'deadline' - list_per_page = 70 # 目的是取消自动分页,好像有bug + list_per_page = 5 # 目的是取消自动分页,好像有bug # raw_id_fields = ("sub_executor",) search_fields = ('todo_topic',) ordering = ('related_task', ) @@ -158,7 +178,158 @@ class TodoAdmin(admin.ModelAdmin): return obj.related_task lined_task.short_description = '任务名称' -# TODO 任务编辑界面按部门显示 + # 导入导出功能限制 + def get_export_formats(self): # 该方法是限制格式为XLS + formats = ( + base_formats.XLS, + ) + return [f for f in formats if f().can_export()] + + def has_import_permission(self, request): # 这是隐藏导入按钮,如果隐藏其他按钮也可以这样操作, + if request.user.is_superuser: + return True + else: + return False + + # 增加批量操作按钮 + actions = ['bulk_action'] + + def bulk_action(self, request, queryset): + post = request.POST + # 这里获取到数据后,可以做些业务处理 + # post中的_action 是方法名 + # post中 _selected 是选中的数据,逗号分割 + if not post.get('_selected'): + return JsonResponse(data={ + 'status': 'error', + 'msg': '请先选中数据!' + }) + else: + return JsonResponse(data={ + 'status': 'success', + 'msg': '处理成功!' + }) + + # 显示的文本,与django admin一致 + bulk_action.short_description = '批量操作' + # icon,参考element-ui icon与https://fontawesome.com + bulk_action.icon = 'el-icon-files' + + # 指定element-ui的按钮类型,参考https://element.eleme.cn/#/zh-CN/component/button + bulk_action.type = 'warning' + + # 给按钮追加自定义的颜色 + bulk_action.style = 'color:white;' + + # 指定为弹出层,这个参数最关键 + bulk_action.layer = { + # 弹出层中的输入框配置 + + # 这里指定对话框的标题 + 'title': '弹出层输入框', + # 提示信息 + 'tips': '这个弹出对话框是需要在admin中进行定义,数据新增编辑等功能,需要自己来实现。', + # 确认按钮显示文本 + 'confirm_button': '确认提交', + # 取消按钮显示文本 + 'cancel_button': '取消', + + # 弹出层对话框的宽度,默认50% + 'width': '40%', + + # 表单中 label的宽度,对应element-ui的 label-width,默认80px + 'labelWidth': "80px", + 'params': [{ + # 这里的type 对应el-input的原生input属性,默认为input + 'type': 'input', + # key 对应post参数中的key + 'key': 'name', + # 显示的文本 + 'label': '名称', + # 为空校验,默认为False + 'require': True + }, { + 'type': 'select', + 'key': 'type', + 'label': '类型', + 'width': '200px', + # size对应elementui的size,取值为:medium / small / mini + 'size': 'small', + # value字段可以指定默认值 + 'value': '0', + 'options': [{ + 'key': '0', + 'label': '收入' + }, { + 'key': '1', + 'label': '支出' + }] + }, { + 'type': 'number', + 'key': 'money', + 'label': '金额', + # 设置默认值 + 'value': 1000 + }, { + 'type': 'date', + 'key': 'date', + 'label': '日期', + }, { + 'type': 'datetime', + 'key': 'datetime', + 'label': '时间', + }, { + 'type': 'rate', + 'key': 'star', + 'label': '评价等级' + }, { + 'type': 'color', + 'key': 'color', + 'label': '颜色' + }, { + 'type': 'slider', + 'key': 'slider', + 'label': '滑块' + }, { + 'type': 'switch', + 'key': 'switch', + 'label': 'switch开关' + }, { + 'type': 'input_number', + 'key': 'input_number', + 'label': 'input number' + }, { + 'type': 'checkbox', + 'key': 'checkbox', + # 必须指定默认值 + 'value': [], + 'label': '复选框', + 'options': [{ + 'key': '0', + 'label': '收入' + }, { + 'key': '1', + 'label': '支出' + }, { + 'key': '2', + 'label': '收益' + }] + }, { + 'type': 'radio', + 'key': 'radio', + 'label': '单选框', + 'options': [{ + 'key': '0', + 'label': '收入' + }, { + 'key': '1', + 'label': '支出' + }, { + 'key': '2', + 'label': '收益' + }] + }] + } admin.site.register(models.Task, TaskAdmin) diff --git a/apps/tasks/resources.py b/apps/tasks/resources.py new file mode 100644 index 0000000..2c7b7d1 --- /dev/null +++ b/apps/tasks/resources.py @@ -0,0 +1,13 @@ +from import_export import resources + +from .models import Todo, Task + + +class TodoResources(resources.ModelResource): + class Meta: + model = Todo + + +class TaskResources(resources.ModelResource): + class Meta: + model = Task diff --git a/apps/tasks/views.py b/apps/tasks/views.py index 34ab1f4..8ae0192 100644 --- a/apps/tasks/views.py +++ b/apps/tasks/views.py @@ -49,7 +49,7 @@ class GroupTodoList(View): class TaskListView(View): @method_decorator(login_required) def get(self, request): - tasks = Task.objects.filter().order_by('task_id') + tasks = Task.objects.filter(department=request.user.department).order_by('task_id') context = {'tasks': tasks} return render(request, 'tasks/tasklist.html', context) diff --git a/apps/users/admin.py b/apps/users/admin.py index 56ef80c..784b094 100644 --- a/apps/users/admin.py +++ b/apps/users/admin.py @@ -23,14 +23,24 @@ class MyUserAdmin(UserAdmin): class MyGroupAdmin(GroupAdmin): pass + class DepartmentAdmin(admin.ModelAdmin): pass + class TaskPropertyAdmin(admin.ModelAdmin): list_display = ( 'task_property', 'own_department' ) + def get_queryset(self, request): + qs = super(TaskPropertyAdmin, self).get_queryset(request) + if request.user.is_superuser: + return qs + else: + return qs.filter(own_department=request.user.department) + + class QualityMarkAdmin(admin.ModelAdmin): list_display = ( 'mark_name', @@ -40,9 +50,27 @@ class QualityMarkAdmin(admin.ModelAdmin): return self.mark_value mark_value.short_description = 'ss' + # # 仅显示当前部门的任务属性,除非为超管 + # def get_queryset(self, request): + # qs = super(QualityMarkAdmin, self).get_queryset(request) + # if request.user.is_superuser: + # return qs + # else: + # return qs.filter(department=request.user.department) + + +class MarkValueAdmin(admin.ModelAdmin): + # def get_queryset(self, request): + # qs = super(MarkValueAdmin, self).get_queryset(request) + # if request.user.is_superuser: + # return qs + # else: + # return qs.filter(department=request.user.department) + pass + admin.site.register(models.User, MyUserAdmin) admin.site.register(models.MyGroup, MyGroupAdmin) -admin.site.register(models.MarkValue) +admin.site.register(models.MarkValue, MarkValueAdmin) admin.site.register(models.Department) admin.site.register(models.QualityMark, QualityMarkAdmin) admin.site.register(models.TaskProperty, TaskPropertyAdmin) diff --git a/requirements.txt b/requirements.txt index a4d8e80..6505438 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,18 @@ asgiref==3.3.1 +defusedxml==0.7.1 +diff-match-patch==20200713 Django==3.1.5 -django-simpleui==2021.3 +django-import-export==2.5.0 +django-simpleui==2021.4.1 +et-xmlfile==1.0.1 +MarkupPy==1.14 +odfpy==1.4.1 +openpyxl==3.0.7 python-dateutil==2.8.1 pytz==2020.5 +PyYAML==5.4.1 six==1.15.0 sqlparse==0.4.1 +tablib==3.0.0 +xlrd==2.0.1 +xlwt==1.3.0