文章目录

  • 1.REST
    • REST介绍
    • HTTP的动词
    • 状态码
  • 2.接口设计开发
    • 基于函数的视图(FBV)
    • 基于类的视图(CBV)
      • 全套接口1:方法重写定制数据
      • 全套接口2:快速开发全套接口
  • 3.下面所提到的功能我们只针对CBV
    • 数据接口分页
      • 单个页面分页
      • 配置全局分页功能
    • 数据接口数据缓存
      • 方法1:使用混入类实现缓存
      • 方法2:使用装饰器实现缓存
    • 数据接口筛选排序操作
      • 方法1:在views视图通过重写get_queryset方法进行筛选和排序
      • 方法2:利用三方库(django-filter)实现筛选排序
    • 数据接口限流

1.REST

REST介绍

REST与技术无关,代表的仅仅是一种架构,一种风格。他的全称为REpresentational State Transfer,意为"表述性信息转移"。
 网络API:主要是强调是通过HTTP(s)请求来请求一个URL获得(json)数据。
 普遍认为,在设计网络接口的时候设计成RESTful API被认为是最好的选择
REST的作者认为:REST是最适合互联网应用的架构。凭什么REST的作者就有勇气认为REST是最适合互联网应用的架构呢?首先HTTP是无状态无连接的,REST架构强调两个词无状态、幂等性。它提出,URL的设计必须使用名词而不能使用动词,我们要用HTTP的动词来表示我们需要做什么操作,因为HTTP的动词已经足够我们进行各种各样的操作。

 幂等性强调的是水平扩展
  - 互联网应用都会面临高并发,所以我们一般都会对系统进行水平扩展:单机结构变多机结构(分布式集群)

HTTP的动词

GET  从服务器取出资源
POST    向服务器添加资源(不需要幂等性)
DELETE  从服务器删除资源
PUT     更新服务器资源(客户端提供改变后的完整资源)
PATCH   更新服务器资源(客户端提供改变的属性)

状态码

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

2.接口设计开发

  • 我们在做数据接口的时候要围绕实体设计,不要围绕业务设计。

做数据接口我们需要安装三方(djangorestframework)

pip install djangorestframework

我们需要在settings.py注册我们的

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',# 注册djangorestframework'rest_framework',
]

基于函数的视图(FBV)

1)Views视图

# 只接受get请求
@api_view(('GET', ))
def get_peovinces(request):"""获取省级行政区域"""# 获取数据库字段为空的数据(指定获取 distid, name) 字段queryset = District.objects.filter(pid__isnull=True).only('distid', 'name')# 对数据进行序列化(加many=True序列化出来是列表,不加就是字典)serializer = DistrictSimpleSerializer(queryset, many=True)return Response(serializer.data)

2)定义序列化器

  • 在当前的apps下新建一个serializer.py,专门用来定义我们的序列化器类
  • 创建一个DistrictSimpleSerializer类
class DistrictSimpleSerializer(serializers.ModelSerializer):"""创建序列化器"""class Meta:# 指定序列化哪个model(表名)model = District# fields:需要保留的字段fields = ('distid', 'name')

3).映射URL

urlpatterns = [path('districts/', get_peovinces),
]

基于类的视图(CBV)

我们在写接口类的时候需要继承父类,下面列几个父类

ListAPIView          查询多个
RetrieveAPIView     查询单个
CreateAPIView       新增数据
DestroyAPIView      删除数据
RetrieveUpdateDestroyAPIView    拿单个/删除/更新

查询接口:定制需要查询字段
1)Views

class EstateView(ListAPIView):"""获取楼盘信息"""queryset = District.objects.all().only('district', 'agents')# 用哪个类来序列化楼盘serializer_class = EstateSerializer

2)定义序列化器

  • 在当前的apps下新建一个serializer.py文件,专门用来定义我们的序列化器类
  • 定义一个EstateSerializer类
class EstateSerializer(serializers.ModelSerializer):class Meta:model = Estateexclude = ('district', 'agents')

3).映射URL

urlpatterns = [path('estates/', EstateView.as_view()),  # 查省
]

全套接口1:方法重写定制数据

1)定义序列化器

  • 在当前的apps下新建一个serializer.py文件,专门用来定义我们的序列化器类
  • 定义一个EstateSerializer类,用于查看(因为我们在查看的时候把地区给排除了)
  • 定义一个EstatePostSerializer类,用于添加与修改
class EstateSerializer(serializers.ModelSerializer):class Meta:model = Estateexclude = ('district', 'agents')class EstatePostSerializer(serializers.ModelSerializer):class Meta:model = Estateexclude = ('agents', )

2).映射URL

urlpatterns = [path('estates/', EstateView.as_view()),# 配置当请求单个的时候传入一个值(pk: pk是一种约定,传入的名字必须叫做pk)path('estates/<int:pk>', EstateView.as_view()),
]

3)Views

class EstateView(ListAPIView, RetrieveAPIView, RetrieveUpdateDestroyAPIView):"""获取楼盘信息"""queryset = District.objects.all().only('district', 'agents')# 用哪个类来序列化楼盘serializer_class = EstateSerializer# 重写方法用来判断走的是什么请求(因为我们在这儿走get的时候设置不看所在区域,但是添加的时候我们需要区域;所以我们另外写了一个序列化器)def get_serializer_class(self):if self.request.method in ('POST', 'PUT', 'PATCH'):return EstatePostSerializerelse:# get 和 delete 走下面这个return EstateSerializer    # 重写get方法区分继承哪个父类的get(多重继承;传入的pk值在request里面)def get(self, request, *args, **kwargs):# 如果request里面有pk返回单个,否则返回多个if 'pk' in kwargs:cls = RetrieveAPIViewelse:cls = ListAPIViewreturn cls.get(self, request, *args, **kwargs)

全套接口2:快速开发全套接口

1)定义序列化器

  • 在当前的apps下新建一个serializer.py文件,专门用来定义我们的序列化器类
  • fields = ‘__all__’ 表示所有的数据都要
class HouseTypeSerializer(serializers.ModelSerializer):class Meta:model = HouseTypefields = '__all__'

2)Views

class HouseTypeViewSet(ModelViewSet):# ReadOnlyModelViewSet  只读接口# ModelViewSet  只读的全套接口queryset = HouseType.objects.all()serializer_class = HouseTypeSerializer

3).映射URL

urlpatterns = [...
]# 配置路由器
router = SimpleRouter()
# 斜杠会自己补,自己不要写斜杠(注册视图集)
router.register('housetypers', HouseTypeViewSet)
# 把urls合并到urlpatterns里面
urlpatterns += router.urls

3.下面所提到的功能我们只针对CBV

数据接口分页

 我们在请求到数据之后我们会对这些数据进行分页处理,这是基本的功能。那么分页又分为游标分页和分页器分页两种。分页器可以配置全局分页,游标分页就得自己在单个页面添加。

单个页面分页

 — 以游标分页为例

在views视图下自定义的分页类

class EstatePagination(CursorPagination):# 页面大小的查询参数(最大不能大于max_page_size)page_size_query_description = 'size'# 默认页面显示的数据为30max_page_size = 30# 根据estated分页ordering = 'estateid'

我们就可以在需要自定义分页页面的views视图类里面加上下面这句即可:

# 指定用自定义的分页类规则进行分页
pagination_class = EstatePagination

配置全局分页功能

 — 以分页器分页为例

我们现在settings.py给rest_framework写一个全局配置

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','debug_toolbar','rest_framework',
]"""
PageNumberPagination    根据页码分页
LimitOffsetPagination   跳过多少条查多少条分页
"""REST_FRAMEWORK = {# 默认的分页类'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',# 每页显示多少条数据'PAGE_SIZE': 5,
}

我们添加了全局分页功能后,每隔页面都会使用我们配置的默认的分页器,但是有些页面我们不需要分页,我们就可以在当前页面的views视图类里面加上:

# 指定当前页不分页
pagination_class = None

数据接口数据缓存

在settings.py配置我们的缓存服务

# 配置redis缓存
CACHES = {'default': {'BACKEND': 'django_redis.cache.RedisCache', # 用 xxx 来做缓存# 连接Redis数据库(服务器地址)# 一主带多从(可以配置个Redis,写走第一台,读走其他的机器)'LOCATION': ['redis://47.98.174.108:6379/0',],'KEY_PREFIX': 'apidemo',   # 把自己的项目名当做文件前缀'OPTIONS': {'CLIENT_CLASS': 'django_redis.client.DefaultClient', # 连接选项(默认,不改)'CONNECTION_POOL_KWARGS': {'max_connections': 512,    # 连接池的连接(最大连接)},'PASSWORD': 'password', # 你的Redis密码}},
}

方法1:使用混入类实现缓存

  • 混入类不能对游标分页进行缓存,所以我们混入类进行缓存的时候我们的分页功能必须是使用的分页器分页

1)drf框架为我们提供了缓存服务,但是我们需要安装三方库**drf-extensions **

pip install drf-extensions

2)添加混入类做我我们的缓存,这么做我们需要在settings.py加入一段配置:

# 做缓存框架的配置
REST_FRAMEWORK_EXTENSIONS = {# 缓存的时间'DEFAULT_CACHE_RESPONSE_TIMEOUT': 120,# 用哪一组进行缓存'DEFAULT_USE_CACHE': 'default',# 单个对象缓存走这一组'DEFAULT_OBJECT_CACHE_KEY_FUNC': 'rest_framework_extensions.utils.default_object_cache_key_func',# 多个对象缓存走这一组'DEFAULT_LIST_CACHE_KEY_FUNC': 'rest_framework_extensions.utils.default_list_cache_key_func',
}

3)views视图我们要把我们的混入类(CacheResponseMixin)加入到最前面

class EstateView(CacheResponseMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):queryset = Estate.objects.all().defer('agents')# 数据筛选filter_backends = (DjangoFilterBackend, OrderingFilter)filterset_class = EstateFilterSet   # 自定义一个类来定义查询条件ordering_fields = ('hot', 'estateid')   # 根据什么来排序def get_serializer_class(self):if self.request.method in ('POST', 'PUT', 'PATCH'):return EstatePostSerializerelse:return EstateSerializerdef get(self, request, *args, **kwargs):if 'pk' in kwargs:cls = RetrieveAPIViewelse:cls = ListAPIViewreturn cls.get(self, request, *args, **kwargs)

方法2:使用装饰器实现缓存

@method_decorator可以把原来装饰函数的装饰器打造成装饰类的装饰器

# 把这个装饰器(cache_page)加到list这个方法上(list在ModelViewSet里面,我们并不需要写)
@method_decorator(decorator=cache_page(timeout=600), name='list')
@method_decorator(decorator=cache_page(timeout=600), name='retrieve')
class HouseTypeViewSet(ModelViewSet):queryset = HouseType.objects.all()serializer_class = HouseTypeSerializerpagination_class = None

数据接口筛选排序操作

方法1:在views视图通过重写get_queryset方法进行筛选和排序

class EstateView(CacheResponseMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):queryset = Estate.objects.all().defer('agents')def get_queryset(self):distid = self.request.GET.get('district')# 实现筛选if distid:self.queryset = self.queryset.filter(district=distid)ordering = self.request.GET.get('ordering')# 实现排序if ordering:self.queryset = self.queryset.order_by(ordering)return self.queryset

方法2:利用三方库(django-filter)实现筛选排序

1)安装三方库(django-filter)

pip install django-filter

2)在settings.py的apps注册我们的三方库

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',# 注册django-filter(会在页面上看到一个过滤器)'django_filters',
]

3)在views视图

 – 3.1 初级筛选(只支持精确查询)

class EstateView(ListCreateAPIView, RetrieveUpdateDestroyAPIView):queryset = Estate.objects.all().defer('agents')# 数据筛选(DjangoFilterBackend),排序(OrderingFilter)filter_backends = (DjangoFilterBackend, OrderingFilter)# 根据哪个列进行筛选(精确筛选)filter_fields = ('district', 'hot')# 根据哪个列进行排序ordering_fields = ('hot', 'estateid')

 – 3.2 高级筛选(需要自定义我们的查询类)

class EstateView(ListCreateAPIView, RetrieveUpdateDestroyAPIView):queryset = Estate.objects.all().defer('agents')# 数据筛选(DjangoFilterBackend),排序(OrderingFilter)filter_backends = (DjangoFilterBackend, OrderingFilter)# 自定义一个过滤类来定义我们的筛选规则filterset_class = EstateFilterSet# 根据哪个列进行排序ordering_fields = ('hot', 'estateid')

 我们在utils.py定义我们的查询类

class EstateFilterSet(django_filters.FilterSet):"""自定义Filterset过滤规则"""# lookup_expr    查找规则# field_name    与哪个字段对应(默认找它的名字[eg: intro])minhot = django_filters.NumberFilter(field_name = 'hot', lookup_expr='gte')maxhot = django_filters.NumberFilter(field_name = 'hot',lookup_expr='lte')# 在单个字段进行搜索# intro = django_filters.CharFilter(lookup_expr='contains')# 在多个字段里面搜索(自定义方法)# method 与下面的方法进行绑定keyword = django_filters.CharFilter(method='filter_by_keyword')@staticmethoddef filter_by_keyword(queryset, key, value):queryset = queryset.filter(Q(name__contains=value) | Q(intro__startswith=value))return queryset

数据接口限流

限流可以对接口访问的频次进行限制,以减轻服务器压力。
它是依赖Redis来进行限流(所以我们要把我们的redis配置好):Redis会记住你的IP地址

在settings.py进行全局配置

REST_FRAMEWORK = {# 默认的限流类(使用速率来限流)'DEFAULT_THROTTLE_CLASSES': ('rest_framework.throttling.AnonRateThrottle',),# 限流的速率'DEFAULT_THROTTLE_RATES': {'anon': '5/min', # 每分钟5次}
}

Django之数据接口开发相关推荐

  1. Django rest_framework 后端接口开发 开发与用户相关的一组接口 登录注册与用户信息查询修改

    Django rest_framework 后端接口开发 开发与用户相关的一组接口 Django DRF框架用起来还是有一些难度的,需要做的配置,需要导的包很多,所以需要多多练习才能掌握它的使用.此文 ...

  2. 如何利用开源插件?又快又好地搞好数据接口开发,连通不同应用系统

    目录 前言介绍: 开源插件 Tapdata PDK 快速开始目标数据库接入 准备环境 下载源码并编译 创建目标数据库的Connector工程 开发完成之后通过 TDD 进行测试验证 如何提交到 PDK ...

  3. 个人中心数据接口的开发

    1. 根据sql语句查询个人中心数据 # 个人中心数据接口开发 @route("/center_data.html") def center_data():# 响应状态status ...

  4. 初识Django —Python API接口编程入门

    初识Django -Python API接口编程入门 一.WEB架构的简单介绍 Django是什么? Django是一个开放源代码的Web应用框架,由Python写成.我们的目标是用Python语言, ...

  5. restful接口开发实例_Restful接口开发与测试—接口测试

    开发完接口,接下来我们需要对我们开发的接口进行测试.接口测试的方法比较多,使用接口工具或者Python来测试都可以,工具方面比如之前我们学习过的Postman或者Jmeter ,Python脚本测试可 ...

  6. Django的前后端分离以及Rest风格接口开发大全

    1.什么是前后端分离开发: 就是前后端工程师约定好数据交互接口,并行的进行开发和测试,后端只提供数据,不负责将数据渲染到页面上,前端通过HTTP请求获取数据并负责将数据渲染到页面上,这个工作是交给浏览 ...

  7. “安居客“住房系统-基于Python-Django前后端分离开发(二)——基于RESTful架构的数据接口配置以及Redis高速缓存

    "安居客"住房系统-基于Python-Django前后端分离开发(二) 基于Django-Rest-Framework创建接口数据(二) 文章目录 "安居客"住 ...

  8. Django框架学习18--虫师web接口开发与自动化测试2--django单元测试与接口开发

    1.django单元测试 在tests.py文件中编写测试类,继承django的TestCase,该类继承自unittest from django.test import TestCase, Cli ...

  9. php接口 汉字出错 空,php接口开发时,数据解析失败问题,字符转义,编码问题(示例代码)...

    php接口开发时,数据解析失败问题,字符转义,编码问题 情景: A平台--->向接口请求数据---->接口向B平台请求数据---->B平台返回数据给接口---->接口返回数据给 ...

最新文章

  1. python chunk 方式读取大文件——本质上还是file read自身支持
  2. 数据分析python够用吗_学数据分析不等于学python
  3. 无招胜有招之Java进阶JVM(三)内存模型
  4. 网络分流器|运营商光纤延距解决方案
  5. python定义一个人类_Python类的定义、继承及类对象使用方法简明教程
  6. oracle主机名的脚本,一个开启Oracle服务和更改主机名的脚本-Oracle
  7. PMP读书笔记(第3章)
  8. map与weakmap,ES6 Map和WeakMap有什么区别?
  9. 新经济、新选择——人才流动与迁徙2021
  10. php header jpg,php header函数输入图片IE不显示问题
  11. .net mysql 工作流_一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core
  12. WebRTC直播技术方案
  13. 随想录(OllyDbg和IDA Pro的配合使用)
  14. 前端 JavaScript 中 JSON.stringify() 的基本用法
  15. FISCO BCOS 区块链 设置交易最晚处理区块高度
  16. 【跃迁之路】【648天】程序员高效学习方法论探索系列(实验阶段405-2018.11.21)...
  17. bootdo 重命名 版本2.0 (适合所有springboot项目)
  18. 计算机屏保的功能,电脑的屏保自动出来格言
  19. 干货丨网站域名后缀都是什么含义?
  20. python学习心得和体会

热门文章

  1. css网页布局小练习,文字案例,小米官网卡片案例
  2. poj 1064 java_poj1064
  3. php错误1064,求助,phpmyadmin导入sql文件提示1064错误
  4. 《吴恩达深度学习》编程作业-第二周
  5. 2.3   文 法 和 语 言 的 形 式 定义
  6. linux下C++基本库的Hollo World程序
  7. jenkins+maven+docker java项目编译、打包、构建镜像、上传私有仓库、web容器部署
  8. 苹果电脑ntfs如何打开硬盘?苹果电脑读写ntfs
  9. el-table 动态多级表头以及数据
  10. Akita与脉冲云的关系