Django REST Framework(DRF)_第四篇
DRF分页(总共三种)
PageNumberPagination(指定第n页,每页显示n条数据)
说明
既然要用人家的那么我们就先来看下源码,这个分页类源码中举例通过参数指定第几页和每页显示的数据:http://api.example.org/accounts/?page=4&page_size=100,所以我们可以知道,请求参数的名称和数值应该都是我们可以自定义的.来,我们来看下面的几个参数:
page_size = api_settings.PAGE_SIZE # 这个是每页显示的数据,我们可以在全局定义,也可以在继承类只定义,比如每页10条记录,这里就设置10
django_paginator_class = DjangoPaginator # 这个是django分页的类,默认即可
page_query_param = 'page' # 第几页参数名称,我们也可以默认使用page,形象生动嘛
page_size_query_param = None # 这个是每页显示记录条数的参数名称,我们可以使用size或者page_size
max_page_size = None # 每页显示数据的最大值,所以page_size要小于这个,这个设置了就表示一页最多能显示多少条数据好了,参数看完了,那我们就来看下方法,实际上分页器核心就是调用paginate_queryset(self, queryset, request, view=None)的方法,返回的是list(self.page),也就是我们传入了queryset数据,并且配置好了页数等信息,最终就返回了第几页的n条数据对象的列表,然后我们再通过序列化之后,通过get_paginated_response(self, data)将序列化后的数据返回给前端即可.好了,我们开始写实例看下吧
使用
首先定义分页器类
from rest_framework.pagination import PageNumberPagination class PageNumberPaginator(PageNumberPagination):
page_size = 10 # 每页显示10条数据
page_size_query_param = 'size' # 每页显示条数的参数名称
page_query_param = 'page' # 页码参数名称,比如page=3&size=10 第三页显示10条
max_page_size = 10 # 最大页码数量控制视图类如下:
from .Paginators import PageNumberPaginator class BookView(APIView):
"""书籍相关视图""" def get(self, request):
book_queryset = Book.objects.all()
# 1.实例化PageNumberPaginator
page_obj = PageNumberPaginator()
# 2.调用paginate_queryset方法获取当前页的数据
page_data = page_obj.paginate_queryset(queryset=book_queryset, request=request, view=self)
# 3.将获取的数据放入序列化器中进行匹配
serializer_data = BookModelSerializer(page_data, many=True)
# 4.返回带超链接的且有上一页和下一页的数据
return page_obj.get_paginated_response(serializer_data.data)
LimitOffsetPagination (偏移n个位置, 向后查看n条数据)
这里就不做多的说明了,直接开始使用,源码跟上一个是类似的.
class LimitOffsetPaginator(LimitOffsetPagination):
default_limit = 2 # 向后查看两条数据
limit_query_param = 'limit' # 查看数据的参数名称
offset_query_param = 'offset' # 偏移参数名称, limit=2&offset=0 这个表示偏移0也就是从第一条数据开始显示,显示两条
max_limit = 999 # 一页查看最多999条数据视图类的话只需要修改实例化类那一行就行了page_obj = LimitOffsetPaginator(),其他都一样
CursorPagination (加密游标的分页,只能有上一页和下一页)
class CursorPaginator(CursorPagination):
cursor_query_param = 'cursor' # 参数名称
page_size = 1 # 每页显示的条数
ordering = '-id' # 根据id倒序排列视图类一样只需要修改实例化那一行 page_obj = CursorPaginator()
访问的分页路径都是自动加密生成的,比如 http://127.0.0.1:8000/app01/books/?cursor=cD0y
ModelViewSet视图类使用分页组件
如果是视图类是继承ModelViewSet写的呢?继承了ModelViewSet后,只需定义queryset和serializer_class序列化器即可,那么怎么玩呢?这个还是得看源码咯,来继续分析源码.
客户端get请求,所以从ModelViewSet -> ListModelMixin -> list方法, list方法中page = self.paginate_queryset(queryset) ,查看paginate_queryset的方法,self指的是视图类,所以从头再找,在GenericViewSet下的GenericAPIView中发现 paginate_queryset的方法下执行了 self.paginator.paginate_queryset(queryset, self.request, view=self) ,此时paginator 方法中又执行了self._paginator = self.pagination_class(), 而pagination_class()就是去配置里面找分页组件类并实例化,因此我们只需要配置pagination_class = PageNumberPaginator即可.
class BooksView(viewsets.ModelViewSet):
queryset = Book.objects
serializer_class = BookModelSerializer
# 指定分页器组件
pagination_class = PageNumberPaginator跨域
简单介绍CORS跨域请求
CORS即Cross Origin Resource Sharing 跨域资源共享,跨域请求分为两种,一种叫简单请求,一种是复杂请求
简单请求和复杂请求
简单请求满足下面要求:
HTTP方法是其中方法之一: HEAD, GET,POST
HTTP头信息不超出以下几种字段
Accept, Accept-Language, Content-Language, Last-Event-ID
Content-Type只能是下列类型中的一个
application/x-www-from-urlencoded
multipart/form-data
text/plain
任何一个不满足上述要求的请求,即会被认为是复杂请求~~
复杂请求会先发出一个预请求,我们也叫预检,OPTIONS请求~~
浏览器的同源策略
上面介绍的是跨域,那么跨域到底为什么会产生呢?其实就是浏览器的同源策略导致的,也就是说浏览器会阻止非同源的请求,非同源指的是域名不同或者不同端口,而且浏览器只会阻止表单及ajax请求,并不会阻止src的请求(script,img标签的)
解决跨域
那么怎么解决跨域呢?
方法一:通过jsonp
jsonp的实现原理是根据浏览器不阻止src请求入手,也就是可以放在window.onload = function () {src="xxx"...}中,这样页面一加载,就会执行代码,但是这种方式太局限了,又不能发送其他类型请求还不能带请求头等,所以这种方法仅作了解
方法二: 添加响应头
因为每个请求都会遇到跨域问题,所以我们可以定义一个中间件,专门处理跨域
from django.utils.deprecation import MiddlewareMixin class CorsMiddleWares(MiddlewareMixin):
def process_response(self, request, response):
# 针对简单请求,允许的地址是所有
response['Access-Control-Allow-Origin'] = '*'
# 如果是复杂请求,一定会先发送option预检
if request.method == "OPTIONS":
# Content-Type也可以写成*,表示任何形式的头都允许
response["Access-Control-Allow-Headers"] = "Content-Type"
response["Access-Control-Allow-Methods"] = "DELETE, PUT, POST"
return response
ContentType的应用
前戏
contenttypes 是Django内置的一个应用,可以追踪项目中所有app和model的对应关系,并记录在ContentType表中。
那么这张表有什么作用呢?接下来我举个例子,网上大部分人都是举该例子,就是商品优惠券和商品的例子,你想下,是不是每个商品都有能有优惠券,那么优惠券设计的结果就会像下面的结构一样,有没有发现如果我们新增一种商品就需要修改表结构,而且大部分字段都是null,所以我们需要修改下表结构
id name food_id cloth_id ....
1 通用优惠券 null null
2 苹果满减券 1 null
3 衬衫满减券 null 1修改后的表结构及数据如下:
id name table_id object_id ....
1 通用优惠券 null null
2 苹果满减券 7(food表) 1(第一行苹果记录)
3 衬衫满减券 8 1你看这样就算再多产品也不会出现空间浪费和表结构修改,而django中的ContentType表.
应用
contenttypes 应用 通过使用contenttypes 应用中提供的特殊字段GenericForeignKey,我们可以很好的解决这个问题。只需要以下三步: from django.contrib.contenttypes.models import ContentType
在model中定义ForeignKey字段,并关联到ContentType表。通常这个字段命名为“content_type” 在model中定义PositiveIntegerField字段(正整数),用来存储关联表中的主键。通常这个字段命名为“object_id” from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
在model中定义GenericForeignKey字段,传入上述两个字段的名字。 为了更方便查询商品的优惠券,我们还可以在商品类中通过GenericRelation字段定义反向关系因此我们在models里面先建立表关系
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import (
GenericForeignKey, GenericRelation
) class Food(models.Model):
name = models.CharField(max_length=32)
price = models.FloatField()
coupon = GenericRelation(to='Coupon') # 用来反向查询 def __str__(self):
return self.name class Clothes(models.Model):
name = models.CharField(max_length=32)
price = models.FloatField()
coupon = GenericRelation(to='Coupon') def __str__(self):
return self.name class Coupon(models.Model):
"""优惠券表模型"""
name = models.CharField(max_length=32)
# 外键关联ContentType,其实这个关系就是要定位到具体的产品表
content_type = models.ForeignKey(to=ContentType, on_delete=models.CASCADE)
# 定位到具体的产品对象,比如苹果的id
object_id = models.PositiveIntegerField()
# 不会生成字段,只是用于关联对象,方便我们通过content_object快速查询到具体产品记录,插入数据时,直接content_object = 产品对象即可,就不需要再一一给content_type和object_id这两个字段赋值了
content_object = GenericForeignKey("content_type", "object_id") def __str__(self):
return self.name表模型创建完成之后,录入基础数据后我们就可以通过字段进行查询了.
class QueryView(View):
def get(self, request):
from .models import Food, Coupon, Clothes # 1.根据苹果立减卷找到苹果商品的价格
# 首先通过苹果立减劵找到coupon的对象
coupon_obj = Coupon.objects.filter(name='苹果立减卷').first()
# 再通过content_object字段就可以直接找到对应的food表记录
pg = coupon_obj.content_object
# 从记录中取出价格字段
pg_price = pg.price # 2.根据苹果找出所有苹果的优惠券
# 先找到苹果的记录对象
food_obj = Food.objects.get(name='苹果')
# 再通过coupon进行反向查询出所有结果,因为是1对多,所以存在多个,用了all()
coupon_queset = food_obj.coupon.all()
print(coupon_queset) # <QuerySet [<Coupon: 苹果满减券>, <Coupon: 苹果立减卷>]> return HttpResponse("OK")注意:ContentType只运用于1对多的关系!!!并且多的那张表中有多个ForeignKey字段。
Django REST Framework(DRF)_第四篇的更多相关文章
- Django REST Framework(DRF)_第三篇
DRF版本控制 介绍 我们在看APIView源码时可以看到,版本和版本控制类是通过determine_version的返回值获取的 version, scheme = self.determine_v ...
- Django REST Framework(DRF)_第二篇
视图和路由 视图封装 第一次封装 上一篇最后我们对书籍表做了增删改查,那么如果现在我们有几十上百张表需要这样做呢?我们知道类的特性有封装,因此我们可以尝试进行封装下. from rest_fram ...
- Django REST Framework(DRF)_第一篇
认识RESTful REST是设计风格而不是标准,简单来讲REST规定url是用来唯一定位资源,而http请求方式则用来区分用户行为. REST接口设计规范 HTTP常用动词 GET /books:列 ...
- Django Rest Framework源码剖析(四)-----API版本
一.简介 在我们给外部提供的API中,可会存在多个版本,不同的版本可能对应的功能不同,所以这时候版本使用就显得尤为重要,django rest framework也为我们提供了多种版本使用方法. 二. ...
- Django 学习之Django Rest Framework(DRF)
一. WEB应用模式 在开发Web应用中,有两种应用模式 1. 前后端不分离 把html模板文件和django的模板语法结合渲染完成以后才从服务器返回给客户. 2. 前后端分离 二. API接口 AP ...
- day71:drf:API接口&Restful API规范&Django Rest Framework&drf中的序列化和反序列化功能
目录 1.web应用模式 2.API接口 3.Restful API规范 4.序列化 5.Django Rest Framework 1.drf的简单介绍 2.drf的特点 3.如何安装drf 4.d ...
- Python笔记_第四篇_高阶编程_进程、线程、协程_5.GPU加速
Numba:高性能计算的高生产率 在这篇文章中,笔者将向你介绍一个来自Anaconda的Python编译器Numba,它可以在CUDA-capable GPU或多核cpu上编译Python代码.Pyt ...
- Python笔记_第四篇_高阶编程_实例化方法、静态方法、类方法和属性方法概念的解析。
1.先叙述静态方法: 我们知道Python调用类的方法的时候都要进行一个实例化的处理.在面向对象中,一把存在静态类,静态方法,动态类.动态方法等乱七八糟的这么一些叫法.其实这些东西看起来抽象,但是很好 ...
- Python全栈开发记录_第四篇(集合、函数等知识点)
知识点1:深拷贝和浅拷贝 非拷贝(=赋值:数据完全共享,内存地址一样,修改一个另一个也变化) 浅拷贝:数据半共享(复制其数据独立内存存放,但是只拷贝成功第一层)像[[1,2],3,4]如果修改列表中列 ...
随机推荐
- Docker部署Nextcloud私有网盘
对于国内某度的网盘限速行为大家有目共睹,不过对于商业化的产品模式这样也无可厚非,毕竟企业也是盈利为目的.如果想享受互联网技术带来的便利,刚好也懂一点技术的话可以尝试搭建属于私有的网盘.个人比较推荐的是 ...
- MySQL知识篇-SQL1
1 SQL是什么? 答:是结构话语言,是一种操作关系型数据库的语言. 2 SQL语言分类? SQL语言 说明 举例 DDL 数据定义语言 create drop DML 数据操作语言 insert ...
- CSS实现网页背景图片自适应全屏,自适应背景图片
一张清晰漂亮的背景图片能给网页加分不少,设计师也经常会给页面的背景使用大图,我们既不想图片因为不同分辨率图片变形,也不希望当在大屏的情况下,背景有一块露白,简而言之,就是实现能自适应屏幕大小又不会变形 ...
- python 之魔法方法
描述符就是将某种特殊类型的类的实例指派给另一个类的属性 例如下面的示例 class MyDecriptor(): def get(self,instance,owner): print("g ...
- MNFTL: An Efficient Flash Translation Layer for MLC
1. we propose two approaches, namely, concentrated mapping and postponed reclamation, to effective r ...
- [转帖]Java高级系列——注解(Annotations)
Java高级系列——注解(Annotations) 2018年01月13日 :: RonTech 阅读数 3405更多 所属专栏: Java高级系列文章 版权声明:转载请注明出处,谢谢配合. http ...
- Vue里标签嵌套限制问题解决------解析DOM模板时注意事项:
受到html本身的一些限制,像<ul>.<ol>.<table>.<select>这样的元素里允许包含的元素有限制,而另一些像<option> ...
- 转 RTSP客户端模拟器(TCP方式,Python实现)
转自: http://www.cnblogs.com/MikeZhang/archive/2012/10/29/rtspTcpClient_DSS_20121029.html 由于某种需求,工作中需要 ...
- MVC4学习要点记一
强类型的辅助方法:这些helper的特征是名称后面加上了 For , 这些叫做强类型的辅助方法. 共用布局页:可以在Views文件夹下面新建一个视图页,命名为_ViewStart.cshtml,将这部 ...
- Linux--目录属性
目录的读属性:表示具有读取目录结构清单的权限.使用ls命令可以将该目录中的文件和子目录的内容列出来. 目录的写属性:表示具有更改目录结构清单的权限.包括以下操作: 建立新的文件与目录 删除已经存在的文 ...