django rest_framework中GenericAPIView配合拓展类mixin或者视图集viewset可以复用其代码,减少自己编写的代码量。下面我要实现自己的视图类,以减少代码量

新建一个myView.py
from collections import OrderedDict

from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from rest_framework.settings import api_settings
from rest_framework.views import APIView class MyView(APIView):
queryset = None # 模型数据
serializer_class = None # 序列化类
filter_class = [] # 过滤字段
lookup_field = 'id' # 删改的查找字段
ordeing_field = ('id',) # 排序字段
pagination_class = None # 分页器 def get_queryset(self):
"""
获取queryset数据列表
"""
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
)
self.queryset = self.queryset.all()
# self.filter_queryset()
return self.queryset def filter_queryset(self, queryset):
"""
过滤queryset数据
"""
search_dict = {}
for fc in self.filter_class:
field = self.request.query_params.dict().get(fc)
if field:
search_dict[fc] = field
queryset = queryset.filter(**search_dict)
return queryset def get_serializer(self, *args, **kwargs):
"""
获取序列化模型
"""
serializer_class = self.get_serializer_class()
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(*args, **kwargs) def get_serializer_class(self):
"""
获取序列化模型类, 判断存在否
"""
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
) return self.serializer_class def get_serializer_context(self): return {
'request': self.request,
'format': self.format_kwarg,
'view': self
} def create(self, request, *args, **kwargs):
"""
创建一条数据
"""
serializer_class = self.get_serializer_class()
serializer = serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED) def update(self, request, *args, **kwargs):
"""
更新修改一条数据
"""
try:
instance = self.queryset.get(id=request.data.get(self.lookup_field))
except Exception:
return Response({'state': 'fail', 'msg': '未找到该数据'}, status=status.HTTP_400_BAD_REQUEST)
serializer_class = self.get_serializer_class()
serializer = serializer_class(instance=instance, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED) def destroy(self, request, *args, **kwargs):
"""
删除数据,传入的时数组,表示可以删除多条
"""
try:
instance = self.queryset.filter(id__in=request.data.get(self.lookup_field))
except Exception:
return Response({'state': 'fail', 'msg': '未找到数据'}, status=status.HTTP_400_BAD_REQUEST)
instance.delete()
return Response({'state': 'success', 'msg': '删除成功'}, status=status.HTTP_204_NO_CONTENT) @property
def paginator(self):
"""
分页器属性
"""
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator def get_paginate_queryset(self, queryset):
"""
获取分页queryset
"""
paginator = self.paginator
if paginator is None:
return None
return paginator.paginate_queryset(
queryset=queryset,
request=self.request,
view=self
) def get_paginated_response(self, data):
"""
获取分页后的返回
"""
assert self.paginator is not None
# print(self.paginator.page.paginator.count)
return self.paginator.get_paginated_response(data) def order_by_queryset(self, queryset):
"""
queryset数据进行排序
"""
return queryset.order_by(*self.ordeing_field) class MyPagination(PageNumberPagination):
page_size = 10 # 表示每页的默认显示数量
max_page_size = 50 # max_page_size:表示每页最大显示数量,做限制使用,避免突然大量的查询数据,数据库崩溃
page_size_query_param = 'page_size' # page_size_query_param:表示url中每页数量参数
page_query_param = 'page_num' # page_query_param:表示url中的页码参数 def get_paginated_response(self, data):
"""
重构分页返回的数据
"""
return Response(OrderedDict([
('total', self.page.paginator.count),
('data', data)
])) class MixinGetPageList:
"""
get只获取分页数据
"""
def get(self, request, *args, **kwargs):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
queryset = self.order_by_queryset(queryset)
serializer_class = self.get_serializer_class()
queryset = self.get_paginate_queryset(queryset)
serializer = serializer_class(queryset, many=True)
return self.get_paginated_response(serializer.data) class MixinGetAllList:
"""
get只获取所有数据
"""
def get(self, request, *args, **kwargs):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
queryset = self.order_by_queryset(queryset)
serializer_class = self.get_serializer_class()
serializer = serializer_class(queryset, many=True)
return Response(serializer.data) class MixinGetList:
"""
get获取分页和所有数据
"""
all_serializer_class = None # 获取所有的序列化类 def get(self, request, *args, **kwargs):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
queryset = self.order_by_queryset(queryset)
params = request.query_params.dict()
if self.pagination_class is not None and params.get('all') is None:
serializer_class = self.get_serializer_class()
queryset = self.get_paginate_queryset(queryset)
serializer = serializer_class(queryset, many=True)
return self.get_paginated_response(serializer.data)
self.serializer_class = self.all_serializer_class
serializer_class = self.get_serializer_class()
serializer = serializer_class(queryset, many=True)
return Response(serializer.data) class MixinPostCreateModel:
"""
post增加数据
"""
def post(self, request):
return self.create(request) class MixinPutUpdateModel:
"""
put修改数据
"""
def put(self, request):
return self.update(request) class MixinDeleteDestroyModel:
"""
delete删除数据
"""
def delete(self, request):
return self.destroy(request) class MyMixin(MyView):
"""
增删改查
"""
def get(self, request, *args, **kwargs): queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
queryset = self.order_by_queryset(queryset) serializer_class = self.get_serializer_class()
if self.pagination_class is not None:
queryset = self.get_paginate_queryset(queryset)
# print(queryset) serializer = serializer_class(queryset, many=True)
return self.get_paginated_response(serializer.data) serializer = serializer_class(queryset, many=True)
return Response(serializer.data) def post(self, request):
return self.create(request) def put(self, request):
return self.update(request) def delete(self, request):
return self.destroy(request)

定义的数据库模型,也就是models.py的模型

class Gender(models.Model):
class Meta:
db_table = 'gender'
name = models.CharField(verbose_name="名字", max_length=16)

序列化文件 serializer.py

class GenderSerializer(serializers.ModelSerializer):
class Meta:
model = models.Gender
fields = '__all__' def create(self, validated_data):
res = models.Gender.objects.create(**validated_data)
return res def update(self, instance, validated_data):
instance.name = validated_data.get('name')
instance.save()
return instance

然后新建一个视图文件

from ani import models
from ani.serializer import GenderSerializer
from utils.myView import MyPagination, MyView, MixinGetList, MixinPostCreateModel, MixinPutUpdateModel, \
MixinDeleteDestroyModel class GenderView(MyView, MixinGetList, MixinPostCreateModel, MixinPutUpdateModel, MixinDeleteDestroyModel):
queryset = models.Gender.objects.all()
serializer_class = GenderSerializer
all_serializer_class = GenderSerializer
filter_class = ['name__icontains']
pagination_class = MyPagination
lookup_field = 'id'
ordeing_field = ('-id',)

依次继承get、post、put、delete,实现查、增、改、删。

接下来对请求参数,及返回参数进行加密,加解密可以看我之前的文章

先新建一个MyResponse.py,自定义自己的返回类

import json

from rest_framework.response import Response

from utils.encryption import setDataAes

class AESResponse(Response):
def __init__(self, data=None, secret='www', status=None, template_name=None, headers=None,
exception=False, content_type=None): enaes_data = setDataAes(secret, json.dumps(data)) super(AESResponse, self).__init__(data=enaes_data, status=status, template_name=template_name, headers=headers,
exception=exception, content_type=content_type)

将myView.py中的Response都替换为自定义返回类,新建了一个myViewEncryp.py

from collections import OrderedDict

from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.pagination import PageNumberPagination from rest_framework.settings import api_settings
from rest_framework.views import APIView from utils.MyResponse import AESResponse
from utils.tools import get_secret class MyView(APIView):
queryset = None # 模型数据
serializer_class = None # 序列化模型
filter_class = [] # 过滤字段
lookup_field = 'id' # 删改的查找字段
ordeing_field = ('id',) # 排序字段
pagination_class = None # 分页器 def get_queryset(self):
"""
获取queryset数据列表
"""
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
)
self.queryset = self.queryset.all()
# self.filter_queryset()
return self.queryset def filter_queryset(self, queryset):
"""
过滤queryset数据
"""
search_dict = {}
for fc in self.filter_class:
field = self.request.query_params.dict().get(fc)
if field:
search_dict[fc] = field
queryset = queryset.filter(**search_dict)
return queryset def get_serializer(self, *args, **kwargs):
"""
获取序列化模型
"""
serializer_class = self.get_serializer_class()
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(*args, **kwargs) def get_serializer_class(self):
"""
获取序列化模型类, 判断存在否
"""
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
) return self.serializer_class def get_serializer_context(self): return {
'request': self.request,
'format': self.format_kwarg,
'view': self
} def create(self, request, *args, **kwargs):
"""
创建一条数据
"""
serializer_class = self.get_serializer_class()
serializer = serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
secret = get_secret(request)
return AESResponse(serializer.data, secret=secret, status=status.HTTP_201_CREATED) def update(self, request, *args, **kwargs):
"""
更新修改一条数据
"""
secret = get_secret(request)
try:
instance = self.queryset.get(id=request.data.get(self.lookup_field))
except Exception:
return AESResponse({'state': 'fail', 'msg': '未找到该数据'}, secret=secret, status=status.HTTP_400_BAD_REQUEST)
serializer_class = self.get_serializer_class()
serializer = serializer_class(instance=instance, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return AESResponse(serializer.data, secret=secret, status=status.HTTP_201_CREATED) def destroy(self, request, *args, **kwargs):
"""
删除数据,传入的时数组,表示可以删除多条
"""
secret = get_secret(request)
try:
instance = self.queryset.filter(id__in=request.data.get(self.lookup_field))
except Exception:
return AESResponse({'state': 'fail', 'msg': '未找到数据'}, secret=secret, status=status.HTTP_400_BAD_REQUEST)
instance.delete()
return AESResponse({'state': 'success', 'msg': '删除成功'}, secret=secret, status=status.HTTP_204_NO_CONTENT) @property
def paginator(self):
"""
分页器属性
"""
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator def get_paginate_queryset(self, queryset):
"""
获取分页queryset
"""
paginator = self.paginator
if paginator is None:
return None
return paginator.paginate_queryset(
queryset=queryset,
request=self.request,
view=self
) def get_paginated_response(self, data):
"""
获取分页后的返回
"""
assert self.paginator is not None
# print(self.paginator.page.paginator.count)
return self.paginator.get_paginated_response(data) def order_by_queryset(self, queryset):
"""
queryset数据进行排序
"""
return queryset.order_by(*self.ordeing_field) class MyPagination(PageNumberPagination):
page_size = 10 # 表示每页的默认显示数量
max_page_size = 50 # max_page_size:表示每页最大显示数量,做限制使用,避免突然大量的查询数据,数据库崩溃
page_size_query_param = 'page_size' # page_size_query_param:表示url中每页数量参数
page_query_param = 'page_num' # page_query_param:表示url中的页码参数 def get_paginated_response(self, data):
"""
重构分页返回的数据
"""
secret = get_secret(self.request)
return AESResponse(OrderedDict([
('total', self.page.paginator.count),
('data', data)
]), secret=secret) class MixinGetPageList:
"""
get只获取分页数据
"""
def get(self, request, *args, **kwargs):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
queryset = self.order_by_queryset(queryset)
serializer_class = self.get_serializer_class()
queryset = self.get_paginate_queryset(queryset)
serializer = serializer_class(queryset, many=True)
return self.get_paginated_response(serializer.data) class MixinGetAllList:
"""
get只获取所有数据
"""
def get(self, request, *args, **kwargs):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
queryset = self.order_by_queryset(queryset)
serializer_class = self.get_serializer_class()
serializer = serializer_class(queryset, many=True) secret = get_secret(request) return AESResponse(serializer.data, secret=secret) class MixinGetList:
"""
get获取分页和所有数据
"""
all_serializer_class = None def get(self, request, *args, **kwargs):
queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
queryset = self.order_by_queryset(queryset)
params = request.query_params.dict()
if self.pagination_class is not None and params.get('all') is None:
serializer_class = self.get_serializer_class()
queryset = self.get_paginate_queryset(queryset)
serializer = serializer_class(queryset, many=True)
return self.get_paginated_response(serializer.data)
self.serializer_class = self.all_serializer_class
serializer_class = self.get_serializer_class()
serializer = serializer_class(queryset, many=True) secret = get_secret(request)
return AESResponse(serializer.data, secret=secret) class MixinPostCreateModel:
"""
post增加数据
"""
def post(self, request):
return self.create(request) class MixinPutUpdateModel:
"""
put修改数据
"""
def put(self, request):
return self.update(request) class MixinDeleteDestroyModel:
"""
delete删除数据
"""
def delete(self, request):
return self.destroy(request) class MyMixin(MyView):
def get(self, request, *args, **kwargs): queryset = self.get_queryset()
queryset = self.filter_queryset(queryset)
queryset = self.order_by_queryset(queryset) serializer_class = self.get_serializer_class()
if self.pagination_class is not None:
queryset = self.get_paginate_queryset(queryset)
# print(queryset) serializer = serializer_class(queryset, many=True)
return self.get_paginated_response(serializer.data) serializer = serializer_class(queryset, many=True) secret = get_secret(request) return AESResponse(serializer.data, secret=secret) def post(self, request):
return self.create(request) def put(self, request):
return self.update(request) def delete(self, request):
return self.destroy(request)

其中加密的密钥是用户的token,或者写死的字符串,tools.py

def get_secret(request):
"""
获取加密的key
"""
return request.META.get('HTTP_AUTHORIZATION') or 'wchime'

如果前端的请求参数加密,那么需要对参数解密,使用装饰器,decorators.py

def request_decrypt(func):
"""
解密请求参数
只对data解密,data传入的必须是字典,不然没有update属性
"""
def wrap(request, *args, **kwargs):
data = request.data
# print(data)
secret = get_secret(request)
decrypt_data = getDataAes(secret, data.get('text'))
if decrypt_data:
data = json.loads(decrypt_data)
del request.data['text']
request.data.update(data)
# print(decrypt_data)
return func(request, *args, **kwargs)
return wrap

这时候视图文件需要装饰器解密

from django.utils.decorators import method_decorator

from ani import models
from ani.serializer import GenderSerializer
from utils.decorators import request_decrypt
from utils.myViewEncryp import MyPagination, MyView, MixinGetList, MixinPostCreateModel, MixinPutUpdateModel, \
MixinDeleteDestroyModel @method_decorator(request_decrypt, name='put')
@method_decorator(request_decrypt, name='delete')
@method_decorator(request_decrypt, name='post')
class GenderView(MyView, MixinGetList, MixinPostCreateModel, MixinPutUpdateModel, MixinDeleteDestroyModel):
queryset = models.Gender.objects.all()
serializer_class = GenderSerializer
all_serializer_class = GenderSerializer
filter_class = ['name__icontains']
pagination_class = MyPagination
lookup_field = 'id'
ordeing_field = ('-id',)

项目文件结构

请求提交参数脚本

import json
import requests from encryption import setDataAes, getDataAes d = {'name': 'aaa'}
body = setDataAes("wchime", json.dumps(d))
url = 'http://127.0.0.1:4000/ani/gender'
print(body)
data = {'text': body}
res = requests.post(url, json=data)
print(res.text)
print(getDataAes("wchime", res.text))

打印结果



Django自定义视图类及实现请求参数和返回参数加解密的更多相关文章

  1. Django 自定义分页类

    分页类代码: class Page(object): ''' 自定义分页类 可以实现Django ORM数据的的分页展示 输出HTML代码: 使用说明: from utils import mypag ...

  2. Django框架视图类

    类视图 在写视图的时候,Django除了使用函数作为视图,也可以使用类作为视图.使用类视图可以使用类的一些特性,比如继承等. View django.views.generic.base.View是主 ...

  3. django自定义管理类的save model和delete model记一次进一步了解

    业务背景: 最近在写一个个人博客网站,文章分类是一个自关联的两层分类.希望在点开分类时,显示一级分类.一级分类下的所有二级分类以及每个二级分类有多少个文章.最简单办法就是关联查询,查询出所有二级分类, ...

  4. [py][mx]django自定义认证类-实现邮箱作为用户名登录

    创建自定义验证用户名密码类CustomBackend users/views.py from django.contrib.auth import authenticate, login from d ...

  5. httpclient工具类,post请求发送json字符串参数,中文乱码处理

    在使用httpclient发送post请求的时候,接收端中文乱码问题解决. 正文: 我们都知道,一般情况下使用post请求是不会出现中文乱码的.可是在使用httpclient发送post请求报文含中文 ...

  6. Spring MVC参数绑定(如何接收请求参数及返回参数)

    在SpringMVC interceptor案例实践中遇到了获取jsp表单传递参数失败的问题,怎么的解决的呢?下面详细介绍. 先讲述下https://www.cnblogs.com/ilovebath ...

  7. Kotlin入门(24)如何自定义视图

    Android提供了丰富多彩的视图与控件,已经能够满足大部分的业务需求,然而计划赶不上变化,总是有意料之外的情况需要特殊处理.比如PagerTabStrip无法在布局文件中指定文本大小和文本颜色,只能 ...

  8. [转载]开发 Spring 自定义视图和视图解析器

    原文出处 http://www.ibm.com/developerworks/cn/java/j-lo-springview/ 概述 Spring 3.0 默认包含了多种视图和视图解析器,比如 JSP ...

  9. Android自定义视图

    Android框架为我们提供了大量的视图类来帮助我们做好展示信息以及同用户进行交互的工作.然后有时候,我们的app或许需要一些在Android内建视图之外特殊的视图,那么此时我们就需要自定义视图.下面 ...

  10. iOS-xib(使用XIB实现嵌套自定义视图)

    参考:http://wtlucky.github.io/geekerprobe/blog/2014/08/10/nested-xib-views/?utm_source=tuicool 因为主要练习x ...

随机推荐

  1. better-scroll横向滚动、纵向滚动

    <div ref="tab" class="tab"> <ul ref="tabWrapper" class=" ...

  2. Vue中使用axios发起POST请求成功,却被挂起

    服务器能接收请求并处理,控制台没有报错,axios().catch也没有捕获异常.随后查看控制台网络页,发现被挂起 在Stack搜到同问题,上面说将axios()函数返回用.then查看被挂起信息.n ...

  3. 通过Navicat导入SQLServer的MDF文件和LDF文件

    新建查询运行: EXEC  sp_attach_db  @dbname  =  '你的数据库名',      @filename1  =  'mdf文件路径(包缀名)',      @filename ...

  4. Redis - 对象结构

    简介 Redis 使用对象存储数据库中的键和值,每当在 Redis 中创建一个新的键值对时,都会创建两个对象:一个是键对象,另一个是值对象. 其中,Redis 的每种对象都由对象结构和对应编码的数据结 ...

  5. go微服务框架kratos学习笔记三(构建单独的http或者grpc demo项目)

    go微服务框架kratos学习笔记三(构建单独的http或者grpc demo项目) 前面两篇跑通了demo项目,和大概了解了kratos demo整体结构,本篇分别构建一个http和一个grpc微服 ...

  6. mapper接口中常见的增删改查

    前言 相信大家在使用mybatis写mapper接口的时候,最常用且简单的方法就是增删改查了.我也是刚开始做项目,在本篇文章中,我将根据自己在vhr微人力项目中的mapper接口方法为实例,记录一下接 ...

  7. Hydra详细使用

    1. 简介 Hydra是什么 Hydra是什么: Hydra是一款网络登录破解工具,可以通过暴力破解方式来猜解用户名和密码,从而获取系统的访问权限.它可以支持多种协议,如FTP.SSH.Telnet. ...

  8. 面试某大厂,被Channel给吊打了,这次一次性通关channel!

    目录 一 前言 面试题 然后我们进行一下扩展,玩转Channel! 二 解决面试题 1. 介绍一下Channel 2. Channel在go中起什么作用 3. Channel为什么需要两个队列实现 4 ...

  9. 做个清醒的程序员之拥抱AI

    阅读时长约 13 分钟,共计约 3100个字. 昨天我体验了AI自动生成短视频,具体说来,首先我在域名为FreeGPT的免费网站,向它提问,然后生成一段文字.之后呢,再用剪映里面的"图文成片 ...

  10. 快速上手Linux核心命令(六):Linux的文本编辑器vi和vim

    @ 目录 前言 简介 小试牛刀 vi/vim 工作原理及三种模式 常用快捷键 命令行图解 前言 上一篇中已经预告,我们这篇主要说Linux中vi/vim 编辑器.它是我们使用Linux系统不可缺少的工 ...