from django_filters.rest_framework import DjangoFilterBackend from rest_framework import status from rest_framework.decorators import action from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.response import Response from rest_framework.viewsets import ModelViewSet from rest_framework.exceptions import ParseError from django.conf import settings from openpyxl import load_workbook, Workbook from django.db import transaction # Create your views here. from .models import Article, Material, Source, Threshold from .serializers import ArticelSerializer, ArticelListSerializer, MaterialSerializer, SourceSerializer, ThresholdSerializer, PathSerializer from utils.custom import CommonPagination class ArticleViewSet(ModelViewSet): """ 文章:增删改查 """ perms_map = [ {'get': '*'}, {'post': 'article_create'}, {'put': 'article_update'}, {'delete': 'article_delete'}] queryset = Article.objects.filter(is_delete=0).all() serializer_class = ArticelSerializer pagination_class = CommonPagination filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter] search_fields = ['title','content'] ordering_fields = ['title','update_time'] ordering = ['-is_top', '-update_time'] def get_serializer_class(self): if self.action=='list': return ArticelListSerializer else: return ArticelSerializer @action(methods=['put'], detail=True, url_name='top_article', perms_map=[{'*':'top_article'}]) def top(self, request, *args, **kwargs): ''' 置顶文章 ''' instance = self.get_object() instance.is_top = False if instance.is_top else True instance.save() return Response(status=status.HTTP_200_OK) class MaterialViewSet(ModelViewSet): """ 资料:增删改查 """ perms_map = [ {'get': '*'}, {'post': 'material_create'}, {'put': 'material_update'}, {'delete': 'material_delete'}] queryset = Material.objects.filter(is_delete=0) serializer_class = MaterialSerializer pagination_class = CommonPagination filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter] search_fields = ['name','description'] ordering_fields = ['update_time', 'down_count'] ordering = ['sort', '-down_count'] filterset_fields = ['type', 'name', 'cate'] @action(methods=['get'], detail=True, url_name='down_material', perms_map=[{'*':'down_material'}]) def down(self, request, *args, **kwargs): ''' 下载资料 ''' instance = self.get_object() instance.down_count = instance.down_count + 1 instance.save() return Response({'path':instance.path, 'down_count':instance.down_count}) class SourceViewSet(ModelViewSet): perms_map = [ {'get': '*'}, {'post': 'threshold_update'}, {'put': 'threshold_update'}, {'delete': 'threshold_update'}] queryset = Source.objects.filter(is_delete=0) pagination_class = CommonPagination filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter] serializer_class = SourceSerializer search_fields = ['name','author'] filterset_fields = ['name', 'author', 'publish_year'] class ThresholdViewSet(ModelViewSet): perms_map = [ {'get': 'threshold_view'}, {'post': 'threshold_update'}, {'put': 'threshold_update'}, {'delete': 'threshold_update'}] queryset = Threshold.objects.filter(is_delete=0) serializer_class = ThresholdSerializer pagination_class = CommonPagination filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter] search_fields = ['chinese_name','cas', 'compound_cate', 'odor_type'] filterset_fields = ['source', 'compound_cate'] @action(methods=['post'], detail=False, perms_map=[{'post':'threshold_update'}], serializer_class=PathSerializer) @transaction.atomic def daoru(self, request, *args, **kwargs): '''导入excel 导入excel ''' data = request.data sr = PathSerializer(data=data) sr.is_valid(raise_exception=True) vdata = sr.validated_data self.handle_xlsx(vdata['path']) return Response() def handle_xlsx(self, path): full_path = settings.BASE_DIR + path if not path.endswith('.xlsx'): raise ParseError('请提供xlsx格式文件') wb = load_workbook(full_path, data_only=True) # 先导入来源 source_sheet = wb.get_sheet_by_name('来源表') i = 3 sources_dict = {} while source_sheet[f'c{i}'].value: item = {} item['name'] = source_sheet[f'c{i}'].value item['author'] = source_sheet[f'd{i}'].value try: item['publish_year'] = int(source_sheet[f'e{i}'].value) except BaseException: pass source, is_created = Source.objects.get_or_create(defaults=item, name=item['name']) sources_dict[str(source_sheet[f'a{i}'].value)] = source i = i + 1 # self.handle_other_sheet(wb, '醇类', sources_dict) # self.handle_other_sheet(wb, '醛类', sources_dict) # self.handle_other_sheet(wb, '酸类', sources_dict) # self.handle_other_sheet(wb, '酯类', sources_dict) # self.handle_other_sheet(wb, '酮类', sources_dict) # self.handle_other_sheet(wb, '醚类', sources_dict) # self.handle_other_sheet(wb, '酚类', sources_dict) # self.handle_other_sheet(wb, '苯系物', sources_dict) # self.handle_other_sheet(wb, '卤代烃', sources_dict) self.handle_other_sheet(wb, '烷烃类', sources_dict) self.handle_other_sheet(wb, '烯烃类', sources_dict) self.handle_other_sheet(wb, '硫化物', sources_dict) self.handle_other_sheet(wb, '胺类', sources_dict) self.handle_other_sheet(wb, '其他', sources_dict) def handle_other_sheet(self, wb: Workbook, name, sources_dict): sheet = wb.get_sheet_by_name(name) i = 2 early_name = '' early_cas = '' while sheet[f'b{i}'].value: item = {} chinese_name = sheet[f'a{i}'].value if chinese_name: early_name = chinese_name else: chinese_name = early_name item['chinese_name'] = chinese_name ppm = sheet[f'b{i}'].value if isinstance(ppm, str): if '<' in ppm or '<' in ppm: item['ppm_sign'] = '<' elif '>' in ppm or '>'in ppm: item['ppm_sign'] = '>' ppm = float(ppm.replace('>', '').replace('<', '').replace('>', '').replace('<', '')) item['ppm'] = ppm mass = sheet[f'c{i}'].value if isinstance(mass, str): if '<' in mass or '<' in mass: item['mass_sign'] = '<' elif '>' in mass or '>'in mass: item['mass_sign'] = '>' mass = float(mass.replace('>', '').replace('<', '').replace('>', '').replace('<', '')) item['mass'] = mass item['molecular'] = sheet[f'd{i}'].value cas = sheet[f'e{i}'].value if cas: early_cas = cas else: cas = early_cas item['cas'] = cas item['odor_type'] = sheet[f'f{i}'].value item['threshold_type'] = sheet[f'g{i}'].value item['source'] = sources_dict[str(sheet[f'h{i}'].value)] item['compound_cate'] = name Threshold.objects.get_or_create(defaults=item, chinese_name=chinese_name, ppm=ppm, mass=mass) i = i + 1