import json import random import warnings from calendar import timegm from datetime import datetime import requests from django.db.models import Q from django_filters.rest_framework import DjangoFilterBackend from openpyxl import Workbook, load_workbook from rest_framework import status from rest_framework.decorators import action from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.viewsets import ModelViewSet from rest_framework_jwt.authentication import JSONWebTokenAuthentication from rest_framework_jwt.serializers import (jwt_encode_handler, jwt_payload_handler) from rest_framework_jwt.settings import api_settings from crm.zhenzismsclient import ZhenziSmsClient from examtest.models_paper import WorkScope from question.models import Questioncat from question.serializers import QuestionSerializer from server import settings from utils.custom import CommonPagination from .exports import export_consumer from .models import Company, Consumer, PaySubject, SendCode from .serializers import CompanySerializer, ConsumerSerializer appid = 'wxf1e9471c93f05ad6' secret = '4bf7f9bd6c52634586bbe792a1f0a834' sms_appid = '100172' sms_appsecret = '00b8681c-0ce6-41c8-a867-904c1891c78a' sms_url = 'https://sms.zhenzikj.com' def jwt_payload_handler(user): payload = { 'user_id': user.pk, 'type':'consumer', 'exp': datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA } if api_settings.JWT_ALLOW_REFRESH: payload['orig_iat'] = timegm( datetime.utcnow().utctimetuple() ) if api_settings.JWT_AUDIENCE is not None: payload['aud'] = api_settings.JWT_AUDIENCE if api_settings.JWT_ISSUER is not None: payload['iss'] = api_settings.JWT_ISSUER return payload class CompanyViewSet(ModelViewSet): """ 客户企业:增删改查 """ perms_map = [ {'get': 'company_list'}, {'post': 'company_create'}, {'put': 'company_update'}, {'delete': 'company_delete'}] queryset = Company.objects.filter(is_delete=0).all() serializer_class = CompanySerializer pagination_class = None #不分页 filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter] search_fields = ('^name',) ordering_fields = ('id',) ordering = ['-id'] class ConsumerViewSet(ModelViewSet): """ 学员:增删改查 """ perms_map = [ {'get': 'consumer_list'}, {'post': 'consumer_create'}, {'put': 'consumer_update'}, {'delete': 'consumer_delete'}] queryset = Consumer.objects.filter(is_delete=0).all() serializer_class = ConsumerSerializer pagination_class = CommonPagination ordering_fields = ('id','company','create_time') ordering = ['-create_time', 'company'] filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filterset_fields = ('company',) search_fields = ('^name','^username') def get_queryset(self): queryset = self.queryset queryset = self.get_serializer_class().setup_eager_loading(queryset) return queryset def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) instance = serializer.save() if request.data.get('subjects', None): for i in request.data.get('subjects'): PaySubject.objects.get_or_create(consumer = instance, subject__id=i, defaults={'consumer':instance,'subject':Questioncat.objects.get(id=i)}) return Response(serializer.data, status=status.HTTP_201_CREATED) def update(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance, data=request.data) if serializer.is_valid(): instance = serializer.save() else: return Response(serializer.errors) PaySubject.objects.filter(consumer = instance).delete() if request.data.get('subjects', None): for i in request.data.get('subjects'): PaySubject.objects.get_or_create(consumer = instance, subject__id=i, defaults={'consumer':instance,'subject':Questioncat.objects.get(id=i)}) return Response(serializer.data) @action(methods=['get'], detail=False, url_path='subjectpaid', url_name='subject_paid',perms_map=[{'*':'my_subject'}]) def has_paid(self, request): """ 当前登陆消费者已付费的学科 """ queryset = PaySubject.objects.filter(consumer = request.user) data = queryset.values_list('subject__id',flat=True) return Response(data) @action(methods=['get'], detail=False, url_path='sendcode', url_name='code_send',authentication_classes=[],permission_classes=[]) def sendcode(self, request): ''' 发送验证码 ''' client = ZhenziSmsClient(sms_url, sms_appid, sms_appsecret) code = random.randint(1000,9999) phone = request.query_params.get('phone') params = {'message':'您的验证码为:' + str(code) +',5分钟内有效', 'number': phone} result = json.loads(client.send(params)) if result['code'] == 0: SendCode.objects.create(phone=phone, code=code) return Response(status=status.HTTP_200_OK) else: return Response({'error':result['data']}) @action(methods=['post','delete','get'], detail=False, url_path='collects', url_name='create_collects', perms_map=[{'*':'my_collects'}]) def collects(self, request): ''' 个人收藏集 ''' if request.method == 'POST': questionId = request.data.get('question',None) if questionId: request.user.collects.remove(questionId) request.user.collects.add(questionId) return Response(status=status.HTTP_200_OK) else: return Response({'error':'post参数错误'}) elif request.method == 'GET': queryset = request.user.collects.all().order_by('-update_time') serializer = QuestionSerializer(instance=queryset,many=True) return Response(serializer.data) elif request.method == 'DELETE': questionId = request.data.get('question',None) if questionId: request.user.collects.remove(questionId) return Response(status=status.HTTP_200_OK) else: return Response({'error':'delete参数错误'}) @action(methods=['post'], detail=False, url_path='import', url_name='import_consumer') def import_consumer(self, request): """ 导入用户 """ xlsxpath = request.data['path'] fullpath = settings.BASE_DIR + xlsxpath wb = load_workbook(fullpath) sheet = wb.worksheets[0] # 验证文件内容 if sheet['a2'].value != '姓名': return Response({"error":"姓名列错误!"}) if sheet['b2'].value != '账户(手机号)': return Response({"error":"账户列错误!"}) if sheet['c2'].value != '单位': return Response({"error":"单位列错误!"}) if sheet['d2'].value != '工作类别': return Response({"error":"工作类别列错误!"}) companydict = {} companys = Company.objects.filter(is_delete=0) for i in companys: companydict[i.name] = i.id m = 3 while sheet['B'+str(m)].value: name = sheet['A'+str(m)].value if name: name = name.replace(' ', '') username = sheet['B'+str(m)].value if username: username = str(username).replace(' ', '') companyname = sheet['C'+str(m)].value if companyname: companyname = companyname.replace(' ', '') if companyname not in companydict: return Response({"error":"不存在单位("+companyname+")!请先新建"}) else: companyobj = Company.objects.get(id=companydict[companyname]) workscope = sheet['d'+str(m)].value if Consumer.objects.filter(username = username).exists(): obj = Consumer.objects.filter(username = username).first() else: obj = Consumer() obj.username = username obj.name = name obj.company = companyobj obj.is_delete = False obj.save() if workscope: workscope = workscope.replace(' ', '') try: workscopeobj = WorkScope.objects.get(name=workscope) obj.workscope = workscopeobj PaySubject.objects.create(subject=workscopeobj.subject, consumer = obj) except: pass obj.save() m = m + 1 return Response(status=status.HTTP_200_OK) @action(methods=['get'], detail=False, url_path='export', url_name='export_consumer', perms_map=[{'*':'export_consumer'}]) def export(self, request): queryset = self.filter_queryset(self.queryset) queryset = ConsumerSerializer.setup_eager_loading(queryset) # 性能优化 serializer = ConsumerSerializer(instance=queryset, many=True) path = export_consumer(serializer.data) return Response({'path': path}) class ConsumerMPLoginView(APIView): """ 小程序登陆颁发token """ authentication_classes=[] permission_classes=[] def post(self, request, *args, **kwargs): code = request.data['code'] info = requests.get('https://api.weixin.qq.com/sns/jscode2session?appid='+appid+'&secret='+secret+'&js_code=' + code+'&grant_type=authorization_code').content.decode('utf-8') info = json.loads(info) openid = info['openid'] session_key = info['session_key'] consumer = Consumer.objects.get_or_create(openid = openid)[0] serializer = ConsumerSerializer(instance=consumer) payload = jwt_payload_handler(consumer) token = jwt_encode_handler(payload) return Response({"token":token,"session_key":session_key, "openid":openid, "userinfo":serializer.data}) class ConsumerLogoutView(APIView): authentication_classes = () permission_classes = () def get(self, request, *args, **kwargs): return Response(status=status.HTTP_200_OK) class ConsumerRegister(APIView): ''' 验证码登陆和注册 ''' def post(self, request, *args, **kwargs): data = request.data phone = data.get('phone', None) code = data.get('code', None) avatar = data.get('avatar', None) nickname = data.get('nickname', None) if phone and code: obj = SendCode.objects.filter(phone=phone).last() if obj: if code == obj.code: # 验证通过 consumer_queryset = Consumer.objects.filter(username=phone) if consumer_queryset.exists(): # 是否存在 consumer = consumer_queryset.first() openid = request.user.openid request.user.delete(soft=False) # 彻底删除 consumer.openid = openid if avatar and nickname: consumer.avatar = avatar consumer.nickname = nickname consumer.is_delete = False consumer.save() return Response(status=status.HTTP_200_OK) else: consumer = request.user consumer.username = phone if avatar and nickname: consumer.avatar = avatar consumer.nickname = nickname consumer.is_delete = False consumer.save() return Response(status=status.HTTP_200_OK) else: return Response({'error':'验证码错误!'}) else: return Response({'error':'认证错误!'}) else: return Response({'error':'信息不全!'})