searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Django1.11框架学习笔记

2023-05-29 09:45:09
59
0
  1. 项目目录介绍
  1. 创建应用程序
  1. 模板templates中编写xx.html,和视图views.py文件分开
    映射规则
  1. 模型
    ORM 对象关系映射
a. 创建数据库表
命令
结果
表名组成结构为:应用名_类名(如:TestModel_test)。
注意:尽管我们没有在 models 给表设置主键,但是 Django 会自动添加一个 id 作为主键。
b. 向表中插入数据
c. 获取数据库所有数据
d. 获取表单数据的方法
(1)get
(2)post
e. request对象
HttpRequest对象包含当前请求URL的一些信息
f. QueryDict对象
在HttpRequest对象中, GET和POST属性是django.http.QueryDict类的实例。
QueryDict类似字典的自定义类,用来处理单键对应多值的情况。
  1. 进入Django后台
  1. 视图
a. 请求对象HttpRequest
常见的属性:get,post,path,method,
b. 相应对象HttpResponse
响应对象主要有三种形式:HttpResponse()、render()、redirect()。
 
 
Django 视图 - FBV 与 CBV
FBV(function base views) 基于函数的视图,就是在视图里使用函数处理请求。
CBV(class base views) 基于类的视图,就是在视图里使用类处理请求。
 
  1. Django路由
    是将url和视图一一对应起来
 
  1. Cookies
    一个 Web 服务器可以分配一个唯一的 session 会话 ID 作为每个 Web 客户端的 cookie,对于客户端的后续请求可以使用接收到的 cookie 来识别。
在Web开发中,使用 session 来完成会话跟踪,session 底层依赖 Cookie 技术。
 
Session(保存在服务端的键值对)
服务器在运行时可以为每一个用户的浏览器创建一个其独享的 session 对象,由于 session 为用户浏览器独享,所以用户在访问服务器的 web 资源时,可以把各自的数据放在各自的 session 中,当用户再去访问该服务器中的其它 web 资源时,其它 web 资源再从用户各自的 session 中取出数据为用户服务。
 
 
  1. 中间件
    Django 中间件是修改 Django request 或者 response 对象的钩子,可以理解为是介于 HttpRequest 与 HttpResponse 处理之间的一道处理过程。
Django 中间件作用:
···修改请求,即传送到 view 中的 HttpRequest 对象。
···修改响应,即 view 返回的 HttpResponse 对象。
 
  1. 项目文件放置
Alt text

Django学习总结

 

Alt text
Alt textAlt text
 
几个比较重要的文件:
– urls.py: 配置URL与响应函数之间的关系
 
– models.py:主要用一个 Python 类来描述数据表。 称为模型(model) 。 运用这个类,你可以通过简单的 Python 的代码来创建、检索、更新、删除 数据库中的记录而无需写一条又一条的SQL语句。描述服务器存储的数据格式(对应数据库中的表)
– views.py:包含了页面的业务逻辑。 latest_books()函数叫做视图。核心,响应request请求,返回给用户html页面;
– templates,名为XX.html的文件放在此处。
相关名词理解
 

Django常用命令

django-admin.py和manage.py基本功能类似,但是区别如下:
常见命令
— 检查工程中是否存在错误(检查完整性)
1.python manage.py check [appname] #命令后面跟APP名称
— 创建Django工程
1.django-admin startproject name [项目想要存放的路径]
— 创建Django应用程序
1.django-admin startapp name [应用想要存放的路径]
2.python manage.py startapp name
— 在当前机器启动一个Web服务器,运行Django项目
1.#默认是8000端口
2.python manage.py runserver
3.#指定IP和端口
4.python manage.py runserver 127.0.0.1:8000
5.#指定端口
6.python manage.py runserver 8000
—Django通过migrations命令将Models中的任何修改写入到数库中,比如:新增加的模型或修改已有的字段等。
**根据models的变化生成对应的Python代码,该代码用于更新数据库
1.python manage.py makemigrations
2.python manage.py makemigrations [appname]
**将model里的修改应用到数据库
1.python manage.py migrate #默认是所有的APP的修改应用到数据库
2.python manage.py migrate [appname] #指定APP的修改应用到数据库
3.python manage.py migrate [appname] [migrations_name] #将操作恢复到指定版本
Django所有的migration信息都保存在django_migrations这个数据库表中
***如果数据库里,已经手动更新了数据库,我们只是想设置当前的migration状态,就使用下面的命令去实现,这个命令并不会真正的去更新数据库。
1.python manage.py migrate blog zero
**输出某一个migrate对应的SQL语句
1.python manage.py sqlmigrate blog 0001_initial

创建一个博客网站

Alt text
  1. 做项目前需要配置好 settings.py
    – 设置域名访问权限
    – 设置templates里的’DIRS’,添加模板目录路径
    – 修改databases设置网站数据库类型
    – 在INSTALLED_APPS中添加APP应用名称
    – 修改项目语言和失去
    – 在项目根目录创建static和media两个目录,static用来存放模板CSS、JS、图片等静态资源,media用来存放上传的文件。并在settings.py里面修改STATIC_URL
  2. Django配置MySQL数据库
    a. 向项目目录下的 __init__.py 添加
1.import pymysql
2.pymysql.install_as_MySQLdb()
b. settings.py文件中DATABASE字段添加MySQL相关信息
1.'ENGINE': 'django.db.backends.mysql', #数据库引擎
2.'NAME': 'blog', #数据库名
3.'USER': 'root', #用户名
4.'PASSWORD': 'zhaosuya1111', #密码
5.'HOST': 'localhost', #数据库主机,默认为localhost
6.'PORT': '3306', #数据库端口,MySQL默认为3306
7.# 'OPTIONS': {'autocommit': True,},
c. 构建models.py
1.index = models.IntegerField(default=999, verbose_name='分类排序')
Django 模型中的verbose_name我们常常可能需要使用。比如将数据库里面的数据导出成csv文件,那么csv文件的表头的名字可以通过取每个字段的verbose_name来获取,数据可以通过queryset语句来获取。verbose_name就是在后台显示对对应的名称
 
d. 视图实现逻辑,templates实现页面,urls定义路由
 
f. 代码优化
当查询语句有很多重复的时候,在views.py文件中可以将重复的查询语句放到一个共有的函数中
 
 

Django Restframework

创建django使用的虚拟环境
 
 
【解决的一个问题】
对于django1和python2.7来说,直接import app 而不是 import project.app
 
 
  1. 序列化
    Django的Forms API非常相似序列化API
    serializers类 and ModelSerializer类
 
在ModelSerializer中,必须写class Meta。
csrf:希望能够从不具有CSRF令牌的客户端对此视图进行POST,因此我们需要将视图标记为csrf_exempt。
可以使用curl或httpie测试我们的服务器。Httpie是用Python编写的用户友好的http客户端
 
  1. 请求与响应
    request.method 返回请求的HTTP方法的 大写 字符串表示形式。
REST框架引入了一个扩展了常规HttpRequest的Request对象,并提供了更灵活的请求解析。Request对象的核心功能是request.data属性,它与request.POST类似,但对于使用Web API更为有用。
 
REST框架还引入了一个Response对象,这是一种获取未渲染(unrendered)内容的TemplateResponse类型,并使用内容协商来确定返回给客户端的正确内容类型。
REST框架提供了两个可用于编写API视图的包装器(wrappers)。
 
这些包装器提供了一些功能,例如确保你在视图中接收到Request实例,并将上下文添加到Response,以便可以执行内容协商。
包装器还提供了诸如在适当时候返回405 Method Not Allowed响应,并处理在使用格式错误的输入来访问request.data时发生的任何ParseError异常。
不再显式地将请求或响应绑定到给定的内容类型。request.data可以处理传入的json请求,但它也可以处理其他格式。同样,我们返回带有数据的响应对象,但允许REST框架将响应给我们渲染成正确的内容类型。
  1. 基于类的试图(CBV)
    在前后端分离的应用模式中,我们通常将后端开发的每个视图都称为一个接口,或者API,前端通过访问接口来对数据进行增删改查。
可以使用基于类的视图编写我们的API视图,而不是基于函数的视图。
将之前所有的函数重构为类的函数
 
优势之一是它可以轻松地创建可复用的行为。
到目前为止,我们使用的创建/获取/更新/删除操作和我们创建的任何基于模型的API视图非常相似。这些常见的行为是在REST框架的mixin类中实现的。
使用GenericAPIView构建视图,并且用上了ListModelMixin和CreateModelMixin。基类提供核心功能,而mixin类提供.list()和.create()操作。然后我们明确地将get和post方法绑定到适当的操作。
 
添加mixins来提供.retrieve()),.update()和.destroy()操作
 
最最最简单 mixed-in
 
  1. 认证和权限
    表示创建代码段的用户,models.py
1.owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)
Django中创建的超级用户
—-1. admin: password123
—-2. sue: password123
—-3. zhao: password123
REST框架包括许多权限类,我们可以使用这些权限类来限制谁可以访问给定的视图,例如:
IsAuthenticatedOrReadOnly类,这将确保经过身份验证的请求获得读写访问权限,未经身份验证的请求将获得只读访问权限。
给视图添加 “登录” 功能
 
users下也能看到对应的snippets对象有哪些
 
对象级别的权限
新建permissions.py文件,导入IsOwnerOrReadOnly类。
==》以代码片段创建者的身份登录的话,“DELETE”和“PUT”操作才会显示在代码片段实例路径上。
 
使用API进行身份验证
http -a tom:password123 POST http://127.0.0.1:8000/snippets/ code="print 789"
  1. 关系和超链接API
    使用REST框架的reverse功能来返回完全限定的URL;第二,URL模式是通过方便的名称来标识。
EST框架提供了两种HTML渲染器,一种用于处理使用模板渲染的HTML,另一种用于处理预渲染的HTML。
实体之间的关系
处理好实体之间的关系是Web API设计中更具挑战性的方面。我们可以选择几种不同的方式来代表一种关系:
 
实体之间超链接的实现方式
HyperlinkedModelSerializer与ModelSerializer有以下区别:
 
  1. 视图集和路由器
    ViewSet类
与View类几乎相同,不同之处在于它们提供诸如read或update之类的操作,而不是get或put等方法处理程序。
ViewSet类只绑定到一组方法处理程序,当它被实例化成一组视图的时候,通常通过使用一个Router类来处理自己定义URL conf的复杂性。
userList类和userDetail类合并为userViewSet类
detail_route装饰器
这个装饰器可用于添加不符合标准create/update/delete样式的任何自定义路径。
默认情况下,使用@detail_route装饰器的自定义操作将响应GET请求。如果我们想要一个响应POST请求的动作,我们可以使用methods参数
最后需要在urls.py文件中将viewset绑定到具体的每个视图。
不需要再自己设计url,直接使用router
使用的DefaultRouter类也会自动为我们创建API根视图,因此我们现在可以从我们的views模块中删除api_root方法。
 
  1. 概要和客户端库
    概要是一种机器可读文档,用于描述可用的API路径,其URLS以及它们支持的操作。概要可以是自动生成文档的有用工具,也可以用于驱动可以与API进行交互的动态客户端库。
    Core API是用于描述API的文档规范。它用于提供可用路径的内部表示形式和API公开的可能的交互。它可以用于服务器端或客户端。
 
相关概念理解:
  1. URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的”.html”后缀名是不必要的,因为这个后缀名表示格式,属于”表现层”范畴,而URI应该只代表”资源”的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对”表现层”的描述。

细节学习

  1. 在models.py文件中创建对应数据库表的类,其中各种类型字段的语法如下:
1.class Article(models.Model):
2. # 常见字符串类型
3. title = models.CharField(max_length=255, unique=True, db_index=True, verbose_name="标题")
4. # 设计ArticleSource类的一个外键
5. source = models.ForeignKey("ArticleSource", verbose_name="来源")
6. # 字典类型,即选项类型
7. article_type_choices = ((0, '资讯'), (1, '视频'))
8. article_type = models.SmallIntegerField(choices=article_type_choices, default=0)
9. # 文本类型
10. brief = models.TextField(max_length=512, verbose_name="摘要")
11. # 时间类型
12. pub_date = models.DateTimeField(verbose_name="上架日期")
13. # 多对多关系
14. tags = models.ManyToManyField("Tags", blank=True, verbose_name="标签")
  1. HTTP的头文件状态
    常用的HTTP动词有下面四个(括号里是对应的SQL命令):
1.GET(SELECT):从服务器取出资源(一项或多项)。
2.POST(CREATE):在服务器新建一个资源。
3.PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
4.DELETE(DELETE):从服务器删除资源。
5.还有三个不常用的HTTP动词。
6.
 
7.PATCH(UPDATE):在服务器更新(更新)资源(客户端提供改变的属性)。
8.HEAD:获取资源的元数据。
9.OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
10.下面是一些例子。
11.
 
12.GET /zoos:列出所有动物园
13.POST /zoos:新建一个动物园(上传文件)
14.GET /zoos/ID:获取某个指定动物园的信息
15.# put和patch的区别
16.PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
17.PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
18.DELETE /zoos/ID:删除某个动物园
19.GET /zoos/ID/animals:列出某个指定动物园的所有动物
20.DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
  1. HTTP返回状态码
    服务器向用户返回的状态码和提示信息,常见的有以下一些
    2开头的是成功的,4开头的是用户方的错误,5开头是服务器方的错误。
1.200 OK - [GET]:服务器成功返回用户请求的数据
2.201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
3.202 Accepted - []:表示一个请求已经进入后台排队(异步任务)
4.204 NO CONTENT - [DELETE]:用户删除数据成功。
5.301 永久重定向;302 临时重定向
6.400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作
7.401 Unauthorized - []:表示用户没有权限(令牌、用户名、密码错误)。
8.403 Forbidden - [] 表示用户得到授权(与401错误相对),但是访问是被禁止的。403拒绝中间件的csrftoken认证
9.404 NOT FOUND - []:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
10.406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
11.410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
12.422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
13.500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
  1. 超链接
    RESTful API最好做到Hypermedia(即返回结果中提供链接,连向其他API方法),使得用户不查文档,也知道下一步应该做什么。
    服务器返回的数据格式,应该尽量使用JSON,避免使用XML。
  2. Django RestFramework在Django原先的基础上进行了一系列改进:
    – 提供了定义序列化serialize的方法,可以快速根据Django ORM或者其他库自动序列化/反序列化;
    – 提供了丰富的类视图(viewSet)、Mixin扩展类,简化视图的编写;
    – 函数视图、类视图、视图集合到自动生成API,满足各种需要。
    – 多种身份认证和权限认证方式的支持;
    – 内置了限流系统;
    – 直观的API web界面;
  3. models.py文件中的类包含的class Meta类:
    通过一个内嵌类 “class Meta” 给你的 model 定义元数据
1.class Meta:
2. verbose_name = "pizza" # 给你的模型类起一个更可读的名字
3. verbose_name_plural = "stories" # 指定模型的复数形式是什么
4. unique_together = (("first_name", "last_name"),) # 当你需要通过两个字段保持唯一性时使用
5. ordering = ['-pub_date', 'author'] # 告诉Django模型对象返回的记录结果集是按照哪个字段排序
6. get_latest_by = "order_date" # 若提供该选项, 该模块将拥有一个 get_latest() 函数以得到 "最新的" 对象(依据那个字段)
7.
 

restframework实现基于函数的视图和基于类的视图

REST框架提供了两个可用于编写API视图的包装器(wrappers)。
– 用于基于函数视图的@api_view装饰器。这样不需要单独写get或者updata函数了(默认情况下只有GET请求会被接受),改变默认行为如下图所示:
 
 
还提供了一组可以加到视图上的装饰器来重写默认设置,这些装饰器必须放在@api_view的下面。
1.# 要创建一个使用限制器确保特定用户每天只能调用一次的视图,可以用@throttle_classes装饰器并给它传递一个限制器类的列表。
2.from rest_framework.decorators import api_view, throttle_classes
3.from rest_framework.throttling import UserRateThrottle
4.class OncePerDayUserThrottle(UserRateThrottle):
5. rate = '1/day'
6.@api_view(['GET'])
7.@throttle_classes([OncePerDayUserThrottle])
8.def view(request):
9. return Response({"message": "Hello for today! See you tomorrow!"})
这些装饰器和上文中的APIView的子类中设置的属性相对应。
其他可用的装饰器有:
 
REST框架直接将响应渲染成正确的内容类型。
– 用于基于类视图的APIView类。
类要继承APIView类
 
基于类的视图的主要优点之一是它们允许你组合一些可重用的行为。使用基于类视图的最大优势之一是它可以轻松地创建可复用的行为。
在APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法
如果你需要在自己的API中自定义返回的错误响应,你需要重写这个方法。
1..handle_exception(self, exc)
– 使用通用的基于类的视图
使用generics,继承自APIView,增加了对于列表视图和详情视图可能用到的通用支持方法。常与Mixin扩展类搭配使用。提供的每个具体通用视图是通过将 GenericAPIView 与一个或多个mixin类组合来构建的。
 
以下属性控制着基本视图的行为。
queryset - 用于从视图返回对象的查询结果集。通常,你必须设置此属性或者重写 get_queryset() 方法。如果你重写了一个视图的方法,重要的是你应该调用 get_queryset() 方法而不是直接访问该属性,因为 queryset 将被计算一次,这些结果将为后续请求缓存起来。
 
serializer_class - 用于验证和反序列化输入以及用于序列化输出的Serializer类。 通常,你必须设置此属性或者重写get_serializer_class() 方法。
lookup_field - 用于执行各个model实例的对象查找的model字段。默认为 'pk'。 请注意,在使用超链接API时,如果需要使用自定义的值,你需要确保在API视图和序列化类都设置查找字段。
get_object(self)返回应用于详细视图的对象实例。默认使用 lookup_field 参数过滤基本的查询集。该方法可以被重写以提供更复杂的行为,例如基于多个 URL 参数的对象查找。
1.def get_object(self):
2. queryset = self.get_queryset()
3. filter = {}
4. for field in self.multiple_lookup_fields:
5. filter[field] = self.kwargs[field]
6.
 
7. obj = get_object_or_404(queryset, **filter)
8. # 请注意,如果你的API不包含任何对象级的权限控制,则不需要下面这句
9. self.check_object_permissions(self.request, obj)
10. return obj
lookup_url_kwarg - 应用于对象查找的URL关键字参数。它的 URL conf 应该包括一个与这个值相对应的关键字参数。如果取消设置,默认情况下使用与 lookup_field相同的值。
– mixin类编写视图
 
五个扩展类:
ListModelMixin,列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。
CreateModelMixin,创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。如果序列化器对前端发送的数据验证失败,返回400错误。
RetrieveModelMixin,详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。如果存在,返回200, 否则返回404。
UpdateModelMixin,更新视图扩展类,提供update(request, args, *kwargs)方法,可以快速实现更新一个存在的数据对象。同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。成功返回200,序列化器校验数据失败时,返回400错误。
DestroyModelMixin,删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。
以下类是具体的通用视图。这通常是你真正用到的那些,除非你需要深度定制的行为。
CreateAPIView 用于 仅创建 端点。提供一个 post 方法处理程序。
扩展: GenericAPIView, CreateModelMixin
ListAPIView 用于 只读 端点以表示模型实例集合 。提供一个 get 方法处理程序。
扩展: GenericAPIView, ListModelMixin
RetrieveAPIView 用于 只读 端点以表示单个模型实例。提供一个 get 方法处理程序。
扩展: GenericAPIView, RetrieveModelMixin
DestroyAPIView 用于 只删除 端点以表示单个模型实例。提供一个 delete 方法处理程序。
扩展: GenericAPIView, DestroyModelMixin
UpdateAPIView 用于 只更新 端点以表示单个模型实例。提供一个 put和patch方法处理程序。
扩展: GenericAPIView, UpdateModelMixin
ListCreateAPIView 用于 读写 端点以表示模型实例的集合。提供一个 get 和 post 方法的处理程序。
扩展: GenericAPIView, ListModelMixin, CreateModelMixin
RetrieveUpdateAPIView用于 读取或更新 端点以表示 单个模型实例。提供 get, put 和 patch 方法的处理程序。
扩展: GenericAPIView, RetrieveModelMixin, UpdateModelMixin
RetrieveDestroyAPIView 用于 读取或删除 端点以表示 单个模型实例。提供 get 和 delete 方法的处理程序。
扩展: GenericAPIView, RetrieveModelMixin, DestroyModelMixin
RetrieveUpdateDestroyAPIView 用于 读写删除 端点以表示 单个模型实例。提供 get, put, patch 和 delete方法的处理程序。
扩展: GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
– 创建自定义 mixins
– ViewSet
REST framework允许将一组相关视图的逻辑组合在单个类ViewSet中,类似于controllers的实现。
它只是一种基于类的视图,不提供任何方法处理程序(如get()或post()),而是提供诸如.list()和. create()之类的操作。
1) ViewSet
继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
– ViewSet 的方法处理程序仅使用 .as_view() 方法绑定到完成视图的相应操作。
1.# 获得两个单独的视图
2.user_list = UserViewSet.as_view({'get': 'list'})
3.user_detail = UserViewSet.as_view({'get': 'retrieve'})
但是 通常我们不会这么做,我们会用一个router来注册我们的viewset,让urlconf自动生成。
1.# 在urls.py文件中完成注册
2.from myapp.views import UserViewSet
3.from rest_framework.routers import DefaultRouter
4.
 
5.router = DefaultRouter()
6.router.register(r'users', UserViewSet)
7.urlpatterns = router.urls
2)GenericViewSet
继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。
3)ModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4)ReadOnlyModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin。
4、视图集中定义附加action动作
1.from rest_framework.decorators import action
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。添加自定义动作需要使用rest_framework.decorators.action装饰器。以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
– methods: 该action支持的请求方式,列表传递
– detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
True 表示使用通过URL获取的主键对应的数据对象
False 表示不使用URL获取主键
 
 

视图View与视图集ViewSet之间的区别

越是封装内容多的类,可定制性、灵活性越差,功能越全面,越是基类可定制性越高,但很多的方法和功能需要开发者定义
 
与使用 View 类相比,使用 ViewSet 类有两个主要优点。
重复的逻辑可以组合成一个类。在上面的例子中,我们只需要指定一次 queryset,它将在多个视图中使用。
通过使用 routers, 哦们不再需要自己处理URLconf。
这两者都有一个权衡。使用常规的 views 和 URL confs 更明确也能够为你提供更多的控制。ViewSets有助于快速启动和运行,或者当你有大型的API,并且希望在整个过程中执行一致的 URL 配置。
个人的经验是会浅层封装 ListModelMixin 为 ListModelView, 其他的能用fbv的时候就用fbv, 因为线上的业务往往涉及到各种情况, 比如增减字段的时候还要考虑兼容旧有字段, 比如可能会依据某一两个字段动态调用不同的serializer来做validator, ModelViewSet 将 validator和serializer合并到一起, 开接口的时候速度很快, 但改接口速度很慢….

RestFramework每一个类细看

  1. requests类
    – 获取来自用户的请求相关的信息
    – 扩展了标准的HttpRequest,添加对框架的灵活请求解析和请求身份验证的支持。
    – 内容协商,允许你实现具体的行为,例如为不同的媒体类型选择不同的序列化方案。
    – request.user 设计rest的认证部分
    请注意,由于实现原因, Request 类并不会从 HttpRequest 类继承, 而是使用合成扩展类。
  2. responses类
    – 该类允许你返回可以呈现为多种内容类型的内容,具体取决于客户端的请求。
    – 除非由于某种原因你要对 REST framework 做大量的自定义,否则你应该始终对返回对象的views使用 APIView 类或者 @api_view 函数。这样做可以确保视图在返回之前能够执行 content negotiation (内容协商)并且为响应选择适当的渲染器。
    【内容协商】一个URL资源服务器可以以多种形式进行相应,但是对于某一个客户端来说,它只需要一种, 所以客户端和服务端得有一种机制来保证,就是内容协商机制。
    – 与常规的 HttpResponse 对象不同,你不能使用渲染内容来实例化一个 Response 对象,而是传递未渲染的数据,包含任何Python基本数据类型。
    – Response 类使用的渲染器无法自行处理像 Django model 实例这样的复杂数据类型,因此你需要在创建 Response 对象之前将数据序列化为基本数据类型。可以使用 REST framework的 Serializer 类来执行此类数据的序列化,或者使用你自定义的来序列化。
    – Response 类扩展了 SimpleTemplateResponse,并且所有常用的属性和方法都是提供的。
  3. 视图相关类之间的继承关系总结
 
  1. 路由器 Routers
    SimpleRouter()类
1.from rest_framework import routers
2.
 
3.router = routers.SimpleRouter()
4.router.register(r'users', UserViewSet)
5.router.register(r'accounts', AccountViewSet)
6.urlpatterns = router.urls
register() 方法有两个必需参数:
 
另一个参数 base_name,如果未设置,basename 将根据视图集的 queryset 属性 (如果它有的话) 自动生成。注意,如果视图集不包含 queryset 属性,那么在注册视图集时必须设置 base_name。
使用action操作来标记路由的额外操作
1.@action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf],
2. url_path='change-password', url_name='change_password')
DefaultRouter类
与SimpleRouter类类似,但是可以返回超链接的相应以及json格式的后缀
  1. 序列化器
1.from rest_framework import serializers
2.class UserSerializer(serializers.Serializer):
序列化器允许将复杂数据 (如查询集和模型实例) 转换为可以轻松渲染成 JSON,XML 或其他内容类型的原生 Python 数据类型。序列化器还提供反序列化,在验证传入的数据之后允许解析数据转换回复杂类型。
在反序列化数据时,在尝试访问经过验证的数据或保存对象实例之前,总是需要调用 is_valid()。如果发生任何验证错误,.errors 属性将包含表示结果错误消息的字典。
 
对象级别验证:
要执行需要访问多个字段的任何其他验证,请添加名为 .validate() 的方法到您的 Serializer 子类中。此方法采用单个参数,该参数是字段值的字典。如果需要,它应该抛出 ValidationError 异常,或者只返回经过验证的值。例如:
1.from rest_framework import serializers
2.
 
3.class EventSerializer(serializers.Serializer):
4. description = serializers.CharField(max_length=100)
5. start = serializers.DateTimeField()
6. finish = serializers.DateTimeField()
7.
 
8. def validate(self, data):
9. """
10. Check that the start is before the stop.
11. """
12. if data['start'] > data['finish']:
13. raise serializers.ValidationError("finish must occur after start")
14. return data
序列化器上的各个字段都可以包含验证器,通过在字段实例上声明
1.def multiple_of_ten(value):
2. if value % 10 != 0:
3. raise serializers.ValidationError('Not a multiple of ten')
4.
 
5.class GameRecord(serializers.Serializer):
6. score = IntegerField(validators=[multiple_of_ten])
7. ...
序列化器类还可以包括应用于完整字段数据集的可重用验证器。通过在内部 Meta 类上声明来包含这些验证器,如下所示:
 
序列器也是一种对象类型,可嵌套实现。
如果嵌套可以接受None值,则需要将required=False标志设置。
 
同样,如果嵌套表示应该是项目列表,则应该将many=True标志设置。
 
当序列器要返回包含超链接关系的对象时,需要序列器能够访问当前的请求以便正确生成完全限定的URL。在实例化序列化器时传递context参数来提供任意的附加上下文。
 
– ModelSerializer
可以自动创建具有与模型字段对应的字段的Serializer类。
ModelSerializer 类与常规 Serializer 类相同,不同之处在于:
 
声明如下:
 
当想确定序列器自动创建了哪些字段和验证器时,使用python manage.py shell,然后导入序列化器,实例化它,并对应对象的表示:
 
– HyperlinkedModelSerializer
它使用超链接来表示关联关系而不是主键。默认情况下,序列化器将包含url字段而不是主键字段。
当实例化 HyperlinkedModelSerializer 时,必须在序列化器上下文中包含当前 request,例如:serializer = AccountSerializer(queryset, context={'request': request})
 
什么情况下使用超链接视图呢:默认情况下,超链接预期对应于匹配样式{model_name}-detail的视图名,并通过pk关键词查找实例。
你可以使用在 extra_kwargs 设置中的 view_name 和 lookup_field 选项中的一个或两个来重写 URL 字段视图名称和查询字段。如下所示:
 
【ps】正确匹配超链接表示和URL配置有时比较困难。可以打印HyperlinkedModelSerializer实例的repr来检查关联关系预映射到哪些视图名称和查询字段。和上面查询序列器自动创建了哪些字段和验证器一样。
– ListSerializer
通常不需要,在实体化序列器设置many=True时,该类将被创建,即序列化器类将成为ListSerializer的子类。
修改是否禁止空列表作为有效输入,默认为True。
– BaseSerializer
可以用来方便的支持可选的序列化和反序列化样式。
实现了与Serializer类相同的API:
  • .data 返回传出的基元表示。
  • .is_valid() 反序列化并验证传入的数据
  • .validated_data 返回经过验证的传入数据
  • .errors 返回在验证期间的任何错误
  • .save() 将验证的数据保存到对象实例中
可以重写四种方法,这取决于你希望序列化器类支持的功能:
  • .to_representation() —— 重写它以支持序列化,用于读取操作。
  • to_internal_value() —— 重写它以支持反序列化,以用于写入操作。
  • create() 和 .update() —— 重写其中一个或两个以支持保存实例。
唯一区别是 BaseSerializer 类不会在可浏览的 API 中生成 HTML 表单。这是因为它们返回的数据不包括允许每个字段被渲染成合适的 HTML 输入的所有字段信息。
  1. 验证器
    除了默认的字段验证,可能会需要将验证逻辑放入可重用的组件中以便后续重用,这时候就需要验证器函数和验证器。验证在序列器上使用。
    当您使用 ModelSerializer 时,所有这些都会自动为您处理。如果您想转而使用 Serializer 类,那么需要显式地定义验证规则。
    • UniqueValidator
有一些模棱两可的情况,您需要显式处理验证,而不是依赖于 ModelSerializer 生成的默认序列化器类。在这些情况下,您可能希望通过为序列化器 Meta.validators 属性指定一个空列表来禁用自动生成的验证器。
 
– 基于函数
验证器可以是任何可调用函数,在失败时引发 serializers.ValidationError。
– 基于字段
将.validate_<field_name>方法添加到Serializer子类来指定自定义字段级验证
– 基于类
使用__call()__方法,允许参数化和重用行为。
  1. 认证 Authentication
    身份验证始终在视图的最开始运行,在权限和限制检查发生之前以及允许任务其他代码继续执行之前。
身份验证本身不会允许或不允许传入的请求,它只识别发出请求的凭证。
–设置身份验证方案:
  • 使用DEFAULT_AUTHENTICATION_CLASSES设置全局默认身份验证方案。
  • 使用基于APIView类的视图在每个视图或者每个视图集的基础上设置身份验证方案。
  • 使用基于函数的视图的@api_view装饰器
– 相关API
  • BasicAuthentication
    必须确保API仅在https上可用,并且确保用户端始终在登录时重新请求用户名和密码并且不会存储这些详细信息到持久存储器中。
  • TokenAuthentication
    使用令牌
  • SessionAuthentication
    – RemoteUserAuthentication
    将身份验证委托给web服务器
    1. Throttling限流
      限流类似于权限,因为它确定是否应该授权请求。限流阀表示临时状态,并用来控制客户端对API的请求速率。对经过身份验证的请求限流较少。
      比如限制用户每分钟最多多少个请求,对于存储服务可能还需要限制带宽,付费数据服务可能限制访问记录的特定数量。
  • 默认在setting中设置全局的默认限流策略
 
  • 使用基于APIView类的视图,在每个视图或者视图集的基础上设置限流策略。
from rest_framework.throttling import UserRateThrottle
  1. 过滤
    当返回结果只想要完整对象集的一个子集时。
    最简单方法是重写GenericAPIView的任何视图的查询集的 .get_queryset()方法。
    举例:
    • 根据用户过滤
 
  • 根据url过滤
 
  1. 分页
    只有在使用通用视图或者视图集时,才会自动执行分页,如果使用APIView,则需要自己调用分页API以确保返回分页响应。
  2. 版本控制
    当启用 API 版本控制时,request.version 属性将包含对应于传入客户端请求中请求的版本的字符串。
 
  1. 测试
    创建测试请求:
1.from rest_framework.test import APIRequestFactory
2.
 
3.# 使用标准 RequestFactory API 创建表单 POST 请求
4.factory = APIRequestFactory()
5.request = factory.post('/notes/', {'title': 'new idea'})
  1. DRF中的认证流程
    共有三种方法
a. session认证
1.rest_framework.authentication.SessionAuthentication
b. jwt认证
json web token,服务器端无需保存token信息
1.rest_framework_jwt.authentication.JSONWebTokenAuthentication
jwt的加密方式
 
jwt和session cookies的不同
JWT 和 Session Cookies 都提供安全的用户身份验证,但是它们有以下几点不同
  • 密码签名
    JWT 具有加密签名,而 Session Cookies 则没有。
  • JSON 是无状态的
    JWT 是无状态的,因为声明被存储在客户端,而不是服务端内存中。
    身份验证可以在本地进行,而不是在请求必须通过服务器数据库或类似位置中进行。这意味着可以对用户进行多次身份验证,而无需与站点或应用程序的数据库进行通信,也无需在此过程中消耗大量资源。
  • 可扩展性
    Session Cookies 是存储在服务器内存中,这就意味着如果网站或者应用很大的情况下会耗费大量的资源。由于 JWT 是无状态的,在许多情况下,它们可以节省服务器资源。因此 JWT 要比 Session Cookies 具有更强的可扩展性。
  • JWT 支持跨域认证
    Session Cookies 只能用在单个节点的域或者它的子域中有效。如果它们尝试通过第三个节点访问,就会被禁止。如果你希望自己的网站和其他站点建立安全连接时,这是一个问题。
    使用 JWT 可以解决这个问题,使用 JWT 能够通过多个节点进行用户认证,也就是我们常说的跨域认证
c. 自定义,基于jwt、其他
继承BaseAuthentication(或其子类),必须重写authentication。
其中authentication中完成:
拿到认证标志 auth
反解析出用户 user
前两步操作失败 返回None => 优客
前两步操作成功 返回user, auth => 登录用户
具体流程
  1. 当用户进行登录的时候,运行了登录类的as_view()方法,进入了APIView类的dispatch方法
  2. 执行self.initialize_request这个方法,里面封装了request和认证对象列表等其他参数
  3. 执行self.initial方法中的self.perform_authentication,里面运行了user方法
  4. 再执行了user方法里面的self._authenticate()方法
    【ps.】以上是drf源码内容,下面为自定义方法
  5. 然后执行了自己定义的类中的authenticate方法,自己定义的类继承了BaseAuthentication类,里面有 authenticate方法,如果自己定义的类中没有authenticate方法会报错
  6. 把从authenticate方法得到的user和auth赋值给user和auth方法
  7. 这两个方法把user和auth的值分别赋值给request.user:是登录用户的对象;request.auth:是认证的信息字典
    具体可以查看APIView的源码,相关资料:关于DRF认证流程的相关资料
  8. 认证
    • 方法一
      系统:
      1)AllowAny:允许所有用户,校验方法直接返回True
      2)IsAuthenticated:只允许登录用户
      必须request.user和request.user.is_authenticated都通过
      3)IsAuthenticatedOrReadOnly:游客只读,登录用户无限制
      get、option、head 请求无限制
      前台请求必须校验 request.user和request.user.is_authenticated
      4)IsAdminUser:是否是后台用户
      校验 request.user和request.user.is_staff is_staff(可以登录后台管理系统的用户)
    • 方法二
      自定义:基于auth的Group与Permission表
      1)自定义权限类,继承BasePermission,重写has_permission
      2)has_permission中完成
      拿到登录用户 user <= request.user
      校验user的分组或是权限
      前两步操作失败 返回False => 无权限
      前两步操作成功 返回True => 有权限
流程
  1. 当用户执行一个业务的时候,运行了as_view方法,进入了APIView类的dispatch方法
  2. (此处不需要封装request了,因为在认证过程中封装了)
  3. 进入self.initial方法中的self.check_permissions(request)方法
  4. 里面执行了for循环,把每个权限类实例化对象

    以上是drf源码内容,下面为自定义方法

  5. 执行自己定义的权限类里面的has_permission方法,里面会判断request.user是否存在
  6. 不存在就返回False,存在就返回True
  7. 之后执行self.permission_denied报错方法,返回的是False就报错,可以自定义报错信息,在has_permission方法中写message = {“status”: False, “error”: “登录成功之后才能评论”},就实现了自定义报错
  8. 如果返回的是True就让他进入功能

WSGI

Python Web Server Gateway Interface,指定了web服务器和Python web应用或web框架之间的标准接口,以提高web应用在一系列web服务器间的移植性
  1. WSGI是一套接口标准协议/规范;
  2. 通信(作用)区间是Web服务器和Python Web应用程序之间;
  3. 目的是制定标准,以保证不同Web服务器可以和不同的Python程序之间相互通信
web服务器在将请求转交给web应用程序之前,需要先将http报文转换为WSGI规定的格式。
0条评论
作者已关闭评论
赵****雅
3文章数
0粉丝数
赵****雅
3 文章 | 0 粉丝
赵****雅
3文章数
0粉丝数
赵****雅
3 文章 | 0 粉丝
原创

Django1.11框架学习笔记

2023-05-29 09:45:09
59
0
  1. 项目目录介绍
  1. 创建应用程序
  1. 模板templates中编写xx.html,和视图views.py文件分开
    映射规则
  1. 模型
    ORM 对象关系映射
a. 创建数据库表
命令
结果
表名组成结构为:应用名_类名(如:TestModel_test)。
注意:尽管我们没有在 models 给表设置主键,但是 Django 会自动添加一个 id 作为主键。
b. 向表中插入数据
c. 获取数据库所有数据
d. 获取表单数据的方法
(1)get
(2)post
e. request对象
HttpRequest对象包含当前请求URL的一些信息
f. QueryDict对象
在HttpRequest对象中, GET和POST属性是django.http.QueryDict类的实例。
QueryDict类似字典的自定义类,用来处理单键对应多值的情况。
  1. 进入Django后台
  1. 视图
a. 请求对象HttpRequest
常见的属性:get,post,path,method,
b. 相应对象HttpResponse
响应对象主要有三种形式:HttpResponse()、render()、redirect()。
 
 
Django 视图 - FBV 与 CBV
FBV(function base views) 基于函数的视图,就是在视图里使用函数处理请求。
CBV(class base views) 基于类的视图,就是在视图里使用类处理请求。
 
  1. Django路由
    是将url和视图一一对应起来
 
  1. Cookies
    一个 Web 服务器可以分配一个唯一的 session 会话 ID 作为每个 Web 客户端的 cookie,对于客户端的后续请求可以使用接收到的 cookie 来识别。
在Web开发中,使用 session 来完成会话跟踪,session 底层依赖 Cookie 技术。
 
Session(保存在服务端的键值对)
服务器在运行时可以为每一个用户的浏览器创建一个其独享的 session 对象,由于 session 为用户浏览器独享,所以用户在访问服务器的 web 资源时,可以把各自的数据放在各自的 session 中,当用户再去访问该服务器中的其它 web 资源时,其它 web 资源再从用户各自的 session 中取出数据为用户服务。
 
 
  1. 中间件
    Django 中间件是修改 Django request 或者 response 对象的钩子,可以理解为是介于 HttpRequest 与 HttpResponse 处理之间的一道处理过程。
Django 中间件作用:
···修改请求,即传送到 view 中的 HttpRequest 对象。
···修改响应,即 view 返回的 HttpResponse 对象。
 
  1. 项目文件放置
Alt text

Django学习总结

 

Alt text
Alt textAlt text
 
几个比较重要的文件:
– urls.py: 配置URL与响应函数之间的关系
 
– models.py:主要用一个 Python 类来描述数据表。 称为模型(model) 。 运用这个类,你可以通过简单的 Python 的代码来创建、检索、更新、删除 数据库中的记录而无需写一条又一条的SQL语句。描述服务器存储的数据格式(对应数据库中的表)
– views.py:包含了页面的业务逻辑。 latest_books()函数叫做视图。核心,响应request请求,返回给用户html页面;
– templates,名为XX.html的文件放在此处。
相关名词理解
 

Django常用命令

django-admin.py和manage.py基本功能类似,但是区别如下:
常见命令
— 检查工程中是否存在错误(检查完整性)
1.python manage.py check [appname] #命令后面跟APP名称
— 创建Django工程
1.django-admin startproject name [项目想要存放的路径]
— 创建Django应用程序
1.django-admin startapp name [应用想要存放的路径]
2.python manage.py startapp name
— 在当前机器启动一个Web服务器,运行Django项目
1.#默认是8000端口
2.python manage.py runserver
3.#指定IP和端口
4.python manage.py runserver 127.0.0.1:8000
5.#指定端口
6.python manage.py runserver 8000
—Django通过migrations命令将Models中的任何修改写入到数库中,比如:新增加的模型或修改已有的字段等。
**根据models的变化生成对应的Python代码,该代码用于更新数据库
1.python manage.py makemigrations
2.python manage.py makemigrations [appname]
**将model里的修改应用到数据库
1.python manage.py migrate #默认是所有的APP的修改应用到数据库
2.python manage.py migrate [appname] #指定APP的修改应用到数据库
3.python manage.py migrate [appname] [migrations_name] #将操作恢复到指定版本
Django所有的migration信息都保存在django_migrations这个数据库表中
***如果数据库里,已经手动更新了数据库,我们只是想设置当前的migration状态,就使用下面的命令去实现,这个命令并不会真正的去更新数据库。
1.python manage.py migrate blog zero
**输出某一个migrate对应的SQL语句
1.python manage.py sqlmigrate blog 0001_initial

创建一个博客网站

Alt text
  1. 做项目前需要配置好 settings.py
    – 设置域名访问权限
    – 设置templates里的’DIRS’,添加模板目录路径
    – 修改databases设置网站数据库类型
    – 在INSTALLED_APPS中添加APP应用名称
    – 修改项目语言和失去
    – 在项目根目录创建static和media两个目录,static用来存放模板CSS、JS、图片等静态资源,media用来存放上传的文件。并在settings.py里面修改STATIC_URL
  2. Django配置MySQL数据库
    a. 向项目目录下的 __init__.py 添加
1.import pymysql
2.pymysql.install_as_MySQLdb()
b. settings.py文件中DATABASE字段添加MySQL相关信息
1.'ENGINE': 'django.db.backends.mysql', #数据库引擎
2.'NAME': 'blog', #数据库名
3.'USER': 'root', #用户名
4.'PASSWORD': 'zhaosuya1111', #密码
5.'HOST': 'localhost', #数据库主机,默认为localhost
6.'PORT': '3306', #数据库端口,MySQL默认为3306
7.# 'OPTIONS': {'autocommit': True,},
c. 构建models.py
1.index = models.IntegerField(default=999, verbose_name='分类排序')
Django 模型中的verbose_name我们常常可能需要使用。比如将数据库里面的数据导出成csv文件,那么csv文件的表头的名字可以通过取每个字段的verbose_name来获取,数据可以通过queryset语句来获取。verbose_name就是在后台显示对对应的名称
 
d. 视图实现逻辑,templates实现页面,urls定义路由
 
f. 代码优化
当查询语句有很多重复的时候,在views.py文件中可以将重复的查询语句放到一个共有的函数中
 
 

Django Restframework

创建django使用的虚拟环境
 
 
【解决的一个问题】
对于django1和python2.7来说,直接import app 而不是 import project.app
 
 
  1. 序列化
    Django的Forms API非常相似序列化API
    serializers类 and ModelSerializer类
 
在ModelSerializer中,必须写class Meta。
csrf:希望能够从不具有CSRF令牌的客户端对此视图进行POST,因此我们需要将视图标记为csrf_exempt。
可以使用curl或httpie测试我们的服务器。Httpie是用Python编写的用户友好的http客户端
 
  1. 请求与响应
    request.method 返回请求的HTTP方法的 大写 字符串表示形式。
REST框架引入了一个扩展了常规HttpRequest的Request对象,并提供了更灵活的请求解析。Request对象的核心功能是request.data属性,它与request.POST类似,但对于使用Web API更为有用。
 
REST框架还引入了一个Response对象,这是一种获取未渲染(unrendered)内容的TemplateResponse类型,并使用内容协商来确定返回给客户端的正确内容类型。
REST框架提供了两个可用于编写API视图的包装器(wrappers)。
 
这些包装器提供了一些功能,例如确保你在视图中接收到Request实例,并将上下文添加到Response,以便可以执行内容协商。
包装器还提供了诸如在适当时候返回405 Method Not Allowed响应,并处理在使用格式错误的输入来访问request.data时发生的任何ParseError异常。
不再显式地将请求或响应绑定到给定的内容类型。request.data可以处理传入的json请求,但它也可以处理其他格式。同样,我们返回带有数据的响应对象,但允许REST框架将响应给我们渲染成正确的内容类型。
  1. 基于类的试图(CBV)
    在前后端分离的应用模式中,我们通常将后端开发的每个视图都称为一个接口,或者API,前端通过访问接口来对数据进行增删改查。
可以使用基于类的视图编写我们的API视图,而不是基于函数的视图。
将之前所有的函数重构为类的函数
 
优势之一是它可以轻松地创建可复用的行为。
到目前为止,我们使用的创建/获取/更新/删除操作和我们创建的任何基于模型的API视图非常相似。这些常见的行为是在REST框架的mixin类中实现的。
使用GenericAPIView构建视图,并且用上了ListModelMixin和CreateModelMixin。基类提供核心功能,而mixin类提供.list()和.create()操作。然后我们明确地将get和post方法绑定到适当的操作。
 
添加mixins来提供.retrieve()),.update()和.destroy()操作
 
最最最简单 mixed-in
 
  1. 认证和权限
    表示创建代码段的用户,models.py
1.owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)
Django中创建的超级用户
—-1. admin: password123
—-2. sue: password123
—-3. zhao: password123
REST框架包括许多权限类,我们可以使用这些权限类来限制谁可以访问给定的视图,例如:
IsAuthenticatedOrReadOnly类,这将确保经过身份验证的请求获得读写访问权限,未经身份验证的请求将获得只读访问权限。
给视图添加 “登录” 功能
 
users下也能看到对应的snippets对象有哪些
 
对象级别的权限
新建permissions.py文件,导入IsOwnerOrReadOnly类。
==》以代码片段创建者的身份登录的话,“DELETE”和“PUT”操作才会显示在代码片段实例路径上。
 
使用API进行身份验证
http -a tom:password123 POST http://127.0.0.1:8000/snippets/ code="print 789"
  1. 关系和超链接API
    使用REST框架的reverse功能来返回完全限定的URL;第二,URL模式是通过方便的名称来标识。
EST框架提供了两种HTML渲染器,一种用于处理使用模板渲染的HTML,另一种用于处理预渲染的HTML。
实体之间的关系
处理好实体之间的关系是Web API设计中更具挑战性的方面。我们可以选择几种不同的方式来代表一种关系:
 
实体之间超链接的实现方式
HyperlinkedModelSerializer与ModelSerializer有以下区别:
 
  1. 视图集和路由器
    ViewSet类
与View类几乎相同,不同之处在于它们提供诸如read或update之类的操作,而不是get或put等方法处理程序。
ViewSet类只绑定到一组方法处理程序,当它被实例化成一组视图的时候,通常通过使用一个Router类来处理自己定义URL conf的复杂性。
userList类和userDetail类合并为userViewSet类
detail_route装饰器
这个装饰器可用于添加不符合标准create/update/delete样式的任何自定义路径。
默认情况下,使用@detail_route装饰器的自定义操作将响应GET请求。如果我们想要一个响应POST请求的动作,我们可以使用methods参数
最后需要在urls.py文件中将viewset绑定到具体的每个视图。
不需要再自己设计url,直接使用router
使用的DefaultRouter类也会自动为我们创建API根视图,因此我们现在可以从我们的views模块中删除api_root方法。
 
  1. 概要和客户端库
    概要是一种机器可读文档,用于描述可用的API路径,其URLS以及它们支持的操作。概要可以是自动生成文档的有用工具,也可以用于驱动可以与API进行交互的动态客户端库。
    Core API是用于描述API的文档规范。它用于提供可用路径的内部表示形式和API公开的可能的交互。它可以用于服务器端或客户端。
 
相关概念理解:
  1. URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的”.html”后缀名是不必要的,因为这个后缀名表示格式,属于”表现层”范畴,而URI应该只代表”资源”的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对”表现层”的描述。

细节学习

  1. 在models.py文件中创建对应数据库表的类,其中各种类型字段的语法如下:
1.class Article(models.Model):
2. # 常见字符串类型
3. title = models.CharField(max_length=255, unique=True, db_index=True, verbose_name="标题")
4. # 设计ArticleSource类的一个外键
5. source = models.ForeignKey("ArticleSource", verbose_name="来源")
6. # 字典类型,即选项类型
7. article_type_choices = ((0, '资讯'), (1, '视频'))
8. article_type = models.SmallIntegerField(choices=article_type_choices, default=0)
9. # 文本类型
10. brief = models.TextField(max_length=512, verbose_name="摘要")
11. # 时间类型
12. pub_date = models.DateTimeField(verbose_name="上架日期")
13. # 多对多关系
14. tags = models.ManyToManyField("Tags", blank=True, verbose_name="标签")
  1. HTTP的头文件状态
    常用的HTTP动词有下面四个(括号里是对应的SQL命令):
1.GET(SELECT):从服务器取出资源(一项或多项)。
2.POST(CREATE):在服务器新建一个资源。
3.PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
4.DELETE(DELETE):从服务器删除资源。
5.还有三个不常用的HTTP动词。
6.
 
7.PATCH(UPDATE):在服务器更新(更新)资源(客户端提供改变的属性)。
8.HEAD:获取资源的元数据。
9.OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
10.下面是一些例子。
11.
 
12.GET /zoos:列出所有动物园
13.POST /zoos:新建一个动物园(上传文件)
14.GET /zoos/ID:获取某个指定动物园的信息
15.# put和patch的区别
16.PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
17.PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
18.DELETE /zoos/ID:删除某个动物园
19.GET /zoos/ID/animals:列出某个指定动物园的所有动物
20.DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
  1. HTTP返回状态码
    服务器向用户返回的状态码和提示信息,常见的有以下一些
    2开头的是成功的,4开头的是用户方的错误,5开头是服务器方的错误。
1.200 OK - [GET]:服务器成功返回用户请求的数据
2.201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
3.202 Accepted - []:表示一个请求已经进入后台排队(异步任务)
4.204 NO CONTENT - [DELETE]:用户删除数据成功。
5.301 永久重定向;302 临时重定向
6.400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作
7.401 Unauthorized - []:表示用户没有权限(令牌、用户名、密码错误)。
8.403 Forbidden - [] 表示用户得到授权(与401错误相对),但是访问是被禁止的。403拒绝中间件的csrftoken认证
9.404 NOT FOUND - []:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
10.406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
11.410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
12.422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
13.500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
  1. 超链接
    RESTful API最好做到Hypermedia(即返回结果中提供链接,连向其他API方法),使得用户不查文档,也知道下一步应该做什么。
    服务器返回的数据格式,应该尽量使用JSON,避免使用XML。
  2. Django RestFramework在Django原先的基础上进行了一系列改进:
    – 提供了定义序列化serialize的方法,可以快速根据Django ORM或者其他库自动序列化/反序列化;
    – 提供了丰富的类视图(viewSet)、Mixin扩展类,简化视图的编写;
    – 函数视图、类视图、视图集合到自动生成API,满足各种需要。
    – 多种身份认证和权限认证方式的支持;
    – 内置了限流系统;
    – 直观的API web界面;
  3. models.py文件中的类包含的class Meta类:
    通过一个内嵌类 “class Meta” 给你的 model 定义元数据
1.class Meta:
2. verbose_name = "pizza" # 给你的模型类起一个更可读的名字
3. verbose_name_plural = "stories" # 指定模型的复数形式是什么
4. unique_together = (("first_name", "last_name"),) # 当你需要通过两个字段保持唯一性时使用
5. ordering = ['-pub_date', 'author'] # 告诉Django模型对象返回的记录结果集是按照哪个字段排序
6. get_latest_by = "order_date" # 若提供该选项, 该模块将拥有一个 get_latest() 函数以得到 "最新的" 对象(依据那个字段)
7.
 

restframework实现基于函数的视图和基于类的视图

REST框架提供了两个可用于编写API视图的包装器(wrappers)。
– 用于基于函数视图的@api_view装饰器。这样不需要单独写get或者updata函数了(默认情况下只有GET请求会被接受),改变默认行为如下图所示:
 
 
还提供了一组可以加到视图上的装饰器来重写默认设置,这些装饰器必须放在@api_view的下面。
1.# 要创建一个使用限制器确保特定用户每天只能调用一次的视图,可以用@throttle_classes装饰器并给它传递一个限制器类的列表。
2.from rest_framework.decorators import api_view, throttle_classes
3.from rest_framework.throttling import UserRateThrottle
4.class OncePerDayUserThrottle(UserRateThrottle):
5. rate = '1/day'
6.@api_view(['GET'])
7.@throttle_classes([OncePerDayUserThrottle])
8.def view(request):
9. return Response({"message": "Hello for today! See you tomorrow!"})
这些装饰器和上文中的APIView的子类中设置的属性相对应。
其他可用的装饰器有:
 
REST框架直接将响应渲染成正确的内容类型。
– 用于基于类视图的APIView类。
类要继承APIView类
 
基于类的视图的主要优点之一是它们允许你组合一些可重用的行为。使用基于类视图的最大优势之一是它可以轻松地创建可复用的行为。
在APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法
如果你需要在自己的API中自定义返回的错误响应,你需要重写这个方法。
1..handle_exception(self, exc)
– 使用通用的基于类的视图
使用generics,继承自APIView,增加了对于列表视图和详情视图可能用到的通用支持方法。常与Mixin扩展类搭配使用。提供的每个具体通用视图是通过将 GenericAPIView 与一个或多个mixin类组合来构建的。
 
以下属性控制着基本视图的行为。
queryset - 用于从视图返回对象的查询结果集。通常,你必须设置此属性或者重写 get_queryset() 方法。如果你重写了一个视图的方法,重要的是你应该调用 get_queryset() 方法而不是直接访问该属性,因为 queryset 将被计算一次,这些结果将为后续请求缓存起来。
 
serializer_class - 用于验证和反序列化输入以及用于序列化输出的Serializer类。 通常,你必须设置此属性或者重写get_serializer_class() 方法。
lookup_field - 用于执行各个model实例的对象查找的model字段。默认为 'pk'。 请注意,在使用超链接API时,如果需要使用自定义的值,你需要确保在API视图和序列化类都设置查找字段。
get_object(self)返回应用于详细视图的对象实例。默认使用 lookup_field 参数过滤基本的查询集。该方法可以被重写以提供更复杂的行为,例如基于多个 URL 参数的对象查找。
1.def get_object(self):
2. queryset = self.get_queryset()
3. filter = {}
4. for field in self.multiple_lookup_fields:
5. filter[field] = self.kwargs[field]
6.
 
7. obj = get_object_or_404(queryset, **filter)
8. # 请注意,如果你的API不包含任何对象级的权限控制,则不需要下面这句
9. self.check_object_permissions(self.request, obj)
10. return obj
lookup_url_kwarg - 应用于对象查找的URL关键字参数。它的 URL conf 应该包括一个与这个值相对应的关键字参数。如果取消设置,默认情况下使用与 lookup_field相同的值。
– mixin类编写视图
 
五个扩展类:
ListModelMixin,列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。
CreateModelMixin,创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。如果序列化器对前端发送的数据验证失败,返回400错误。
RetrieveModelMixin,详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。如果存在,返回200, 否则返回404。
UpdateModelMixin,更新视图扩展类,提供update(request, args, *kwargs)方法,可以快速实现更新一个存在的数据对象。同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。成功返回200,序列化器校验数据失败时,返回400错误。
DestroyModelMixin,删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。
以下类是具体的通用视图。这通常是你真正用到的那些,除非你需要深度定制的行为。
CreateAPIView 用于 仅创建 端点。提供一个 post 方法处理程序。
扩展: GenericAPIView, CreateModelMixin
ListAPIView 用于 只读 端点以表示模型实例集合 。提供一个 get 方法处理程序。
扩展: GenericAPIView, ListModelMixin
RetrieveAPIView 用于 只读 端点以表示单个模型实例。提供一个 get 方法处理程序。
扩展: GenericAPIView, RetrieveModelMixin
DestroyAPIView 用于 只删除 端点以表示单个模型实例。提供一个 delete 方法处理程序。
扩展: GenericAPIView, DestroyModelMixin
UpdateAPIView 用于 只更新 端点以表示单个模型实例。提供一个 put和patch方法处理程序。
扩展: GenericAPIView, UpdateModelMixin
ListCreateAPIView 用于 读写 端点以表示模型实例的集合。提供一个 get 和 post 方法的处理程序。
扩展: GenericAPIView, ListModelMixin, CreateModelMixin
RetrieveUpdateAPIView用于 读取或更新 端点以表示 单个模型实例。提供 get, put 和 patch 方法的处理程序。
扩展: GenericAPIView, RetrieveModelMixin, UpdateModelMixin
RetrieveDestroyAPIView 用于 读取或删除 端点以表示 单个模型实例。提供 get 和 delete 方法的处理程序。
扩展: GenericAPIView, RetrieveModelMixin, DestroyModelMixin
RetrieveUpdateDestroyAPIView 用于 读写删除 端点以表示 单个模型实例。提供 get, put, patch 和 delete方法的处理程序。
扩展: GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
– 创建自定义 mixins
– ViewSet
REST framework允许将一组相关视图的逻辑组合在单个类ViewSet中,类似于controllers的实现。
它只是一种基于类的视图,不提供任何方法处理程序(如get()或post()),而是提供诸如.list()和. create()之类的操作。
1) ViewSet
继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
– ViewSet 的方法处理程序仅使用 .as_view() 方法绑定到完成视图的相应操作。
1.# 获得两个单独的视图
2.user_list = UserViewSet.as_view({'get': 'list'})
3.user_detail = UserViewSet.as_view({'get': 'retrieve'})
但是 通常我们不会这么做,我们会用一个router来注册我们的viewset,让urlconf自动生成。
1.# 在urls.py文件中完成注册
2.from myapp.views import UserViewSet
3.from rest_framework.routers import DefaultRouter
4.
 
5.router = DefaultRouter()
6.router.register(r'users', UserViewSet)
7.urlpatterns = router.urls
2)GenericViewSet
继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。
3)ModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4)ReadOnlyModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin。
4、视图集中定义附加action动作
1.from rest_framework.decorators import action
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。添加自定义动作需要使用rest_framework.decorators.action装饰器。以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
– methods: 该action支持的请求方式,列表传递
– detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
True 表示使用通过URL获取的主键对应的数据对象
False 表示不使用URL获取主键
 
 

视图View与视图集ViewSet之间的区别

越是封装内容多的类,可定制性、灵活性越差,功能越全面,越是基类可定制性越高,但很多的方法和功能需要开发者定义
 
与使用 View 类相比,使用 ViewSet 类有两个主要优点。
重复的逻辑可以组合成一个类。在上面的例子中,我们只需要指定一次 queryset,它将在多个视图中使用。
通过使用 routers, 哦们不再需要自己处理URLconf。
这两者都有一个权衡。使用常规的 views 和 URL confs 更明确也能够为你提供更多的控制。ViewSets有助于快速启动和运行,或者当你有大型的API,并且希望在整个过程中执行一致的 URL 配置。
个人的经验是会浅层封装 ListModelMixin 为 ListModelView, 其他的能用fbv的时候就用fbv, 因为线上的业务往往涉及到各种情况, 比如增减字段的时候还要考虑兼容旧有字段, 比如可能会依据某一两个字段动态调用不同的serializer来做validator, ModelViewSet 将 validator和serializer合并到一起, 开接口的时候速度很快, 但改接口速度很慢….

RestFramework每一个类细看

  1. requests类
    – 获取来自用户的请求相关的信息
    – 扩展了标准的HttpRequest,添加对框架的灵活请求解析和请求身份验证的支持。
    – 内容协商,允许你实现具体的行为,例如为不同的媒体类型选择不同的序列化方案。
    – request.user 设计rest的认证部分
    请注意,由于实现原因, Request 类并不会从 HttpRequest 类继承, 而是使用合成扩展类。
  2. responses类
    – 该类允许你返回可以呈现为多种内容类型的内容,具体取决于客户端的请求。
    – 除非由于某种原因你要对 REST framework 做大量的自定义,否则你应该始终对返回对象的views使用 APIView 类或者 @api_view 函数。这样做可以确保视图在返回之前能够执行 content negotiation (内容协商)并且为响应选择适当的渲染器。
    【内容协商】一个URL资源服务器可以以多种形式进行相应,但是对于某一个客户端来说,它只需要一种, 所以客户端和服务端得有一种机制来保证,就是内容协商机制。
    – 与常规的 HttpResponse 对象不同,你不能使用渲染内容来实例化一个 Response 对象,而是传递未渲染的数据,包含任何Python基本数据类型。
    – Response 类使用的渲染器无法自行处理像 Django model 实例这样的复杂数据类型,因此你需要在创建 Response 对象之前将数据序列化为基本数据类型。可以使用 REST framework的 Serializer 类来执行此类数据的序列化,或者使用你自定义的来序列化。
    – Response 类扩展了 SimpleTemplateResponse,并且所有常用的属性和方法都是提供的。
  3. 视图相关类之间的继承关系总结
 
  1. 路由器 Routers
    SimpleRouter()类
1.from rest_framework import routers
2.
 
3.router = routers.SimpleRouter()
4.router.register(r'users', UserViewSet)
5.router.register(r'accounts', AccountViewSet)
6.urlpatterns = router.urls
register() 方法有两个必需参数:
 
另一个参数 base_name,如果未设置,basename 将根据视图集的 queryset 属性 (如果它有的话) 自动生成。注意,如果视图集不包含 queryset 属性,那么在注册视图集时必须设置 base_name。
使用action操作来标记路由的额外操作
1.@action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf],
2. url_path='change-password', url_name='change_password')
DefaultRouter类
与SimpleRouter类类似,但是可以返回超链接的相应以及json格式的后缀
  1. 序列化器
1.from rest_framework import serializers
2.class UserSerializer(serializers.Serializer):
序列化器允许将复杂数据 (如查询集和模型实例) 转换为可以轻松渲染成 JSON,XML 或其他内容类型的原生 Python 数据类型。序列化器还提供反序列化,在验证传入的数据之后允许解析数据转换回复杂类型。
在反序列化数据时,在尝试访问经过验证的数据或保存对象实例之前,总是需要调用 is_valid()。如果发生任何验证错误,.errors 属性将包含表示结果错误消息的字典。
 
对象级别验证:
要执行需要访问多个字段的任何其他验证,请添加名为 .validate() 的方法到您的 Serializer 子类中。此方法采用单个参数,该参数是字段值的字典。如果需要,它应该抛出 ValidationError 异常,或者只返回经过验证的值。例如:
1.from rest_framework import serializers
2.
 
3.class EventSerializer(serializers.Serializer):
4. description = serializers.CharField(max_length=100)
5. start = serializers.DateTimeField()
6. finish = serializers.DateTimeField()
7.
 
8. def validate(self, data):
9. """
10. Check that the start is before the stop.
11. """
12. if data['start'] > data['finish']:
13. raise serializers.ValidationError("finish must occur after start")
14. return data
序列化器上的各个字段都可以包含验证器,通过在字段实例上声明
1.def multiple_of_ten(value):
2. if value % 10 != 0:
3. raise serializers.ValidationError('Not a multiple of ten')
4.
 
5.class GameRecord(serializers.Serializer):
6. score = IntegerField(validators=[multiple_of_ten])
7. ...
序列化器类还可以包括应用于完整字段数据集的可重用验证器。通过在内部 Meta 类上声明来包含这些验证器,如下所示:
 
序列器也是一种对象类型,可嵌套实现。
如果嵌套可以接受None值,则需要将required=False标志设置。
 
同样,如果嵌套表示应该是项目列表,则应该将many=True标志设置。
 
当序列器要返回包含超链接关系的对象时,需要序列器能够访问当前的请求以便正确生成完全限定的URL。在实例化序列化器时传递context参数来提供任意的附加上下文。
 
– ModelSerializer
可以自动创建具有与模型字段对应的字段的Serializer类。
ModelSerializer 类与常规 Serializer 类相同,不同之处在于:
 
声明如下:
 
当想确定序列器自动创建了哪些字段和验证器时,使用python manage.py shell,然后导入序列化器,实例化它,并对应对象的表示:
 
– HyperlinkedModelSerializer
它使用超链接来表示关联关系而不是主键。默认情况下,序列化器将包含url字段而不是主键字段。
当实例化 HyperlinkedModelSerializer 时,必须在序列化器上下文中包含当前 request,例如:serializer = AccountSerializer(queryset, context={'request': request})
 
什么情况下使用超链接视图呢:默认情况下,超链接预期对应于匹配样式{model_name}-detail的视图名,并通过pk关键词查找实例。
你可以使用在 extra_kwargs 设置中的 view_name 和 lookup_field 选项中的一个或两个来重写 URL 字段视图名称和查询字段。如下所示:
 
【ps】正确匹配超链接表示和URL配置有时比较困难。可以打印HyperlinkedModelSerializer实例的repr来检查关联关系预映射到哪些视图名称和查询字段。和上面查询序列器自动创建了哪些字段和验证器一样。
– ListSerializer
通常不需要,在实体化序列器设置many=True时,该类将被创建,即序列化器类将成为ListSerializer的子类。
修改是否禁止空列表作为有效输入,默认为True。
– BaseSerializer
可以用来方便的支持可选的序列化和反序列化样式。
实现了与Serializer类相同的API:
  • .data 返回传出的基元表示。
  • .is_valid() 反序列化并验证传入的数据
  • .validated_data 返回经过验证的传入数据
  • .errors 返回在验证期间的任何错误
  • .save() 将验证的数据保存到对象实例中
可以重写四种方法,这取决于你希望序列化器类支持的功能:
  • .to_representation() —— 重写它以支持序列化,用于读取操作。
  • to_internal_value() —— 重写它以支持反序列化,以用于写入操作。
  • create() 和 .update() —— 重写其中一个或两个以支持保存实例。
唯一区别是 BaseSerializer 类不会在可浏览的 API 中生成 HTML 表单。这是因为它们返回的数据不包括允许每个字段被渲染成合适的 HTML 输入的所有字段信息。
  1. 验证器
    除了默认的字段验证,可能会需要将验证逻辑放入可重用的组件中以便后续重用,这时候就需要验证器函数和验证器。验证在序列器上使用。
    当您使用 ModelSerializer 时,所有这些都会自动为您处理。如果您想转而使用 Serializer 类,那么需要显式地定义验证规则。
    • UniqueValidator
有一些模棱两可的情况,您需要显式处理验证,而不是依赖于 ModelSerializer 生成的默认序列化器类。在这些情况下,您可能希望通过为序列化器 Meta.validators 属性指定一个空列表来禁用自动生成的验证器。
 
– 基于函数
验证器可以是任何可调用函数,在失败时引发 serializers.ValidationError。
– 基于字段
将.validate_<field_name>方法添加到Serializer子类来指定自定义字段级验证
– 基于类
使用__call()__方法,允许参数化和重用行为。
  1. 认证 Authentication
    身份验证始终在视图的最开始运行,在权限和限制检查发生之前以及允许任务其他代码继续执行之前。
身份验证本身不会允许或不允许传入的请求,它只识别发出请求的凭证。
–设置身份验证方案:
  • 使用DEFAULT_AUTHENTICATION_CLASSES设置全局默认身份验证方案。
  • 使用基于APIView类的视图在每个视图或者每个视图集的基础上设置身份验证方案。
  • 使用基于函数的视图的@api_view装饰器
– 相关API
  • BasicAuthentication
    必须确保API仅在https上可用,并且确保用户端始终在登录时重新请求用户名和密码并且不会存储这些详细信息到持久存储器中。
  • TokenAuthentication
    使用令牌
  • SessionAuthentication
    – RemoteUserAuthentication
    将身份验证委托给web服务器
    1. Throttling限流
      限流类似于权限,因为它确定是否应该授权请求。限流阀表示临时状态,并用来控制客户端对API的请求速率。对经过身份验证的请求限流较少。
      比如限制用户每分钟最多多少个请求,对于存储服务可能还需要限制带宽,付费数据服务可能限制访问记录的特定数量。
  • 默认在setting中设置全局的默认限流策略
 
  • 使用基于APIView类的视图,在每个视图或者视图集的基础上设置限流策略。
from rest_framework.throttling import UserRateThrottle
  1. 过滤
    当返回结果只想要完整对象集的一个子集时。
    最简单方法是重写GenericAPIView的任何视图的查询集的 .get_queryset()方法。
    举例:
    • 根据用户过滤
 
  • 根据url过滤
 
  1. 分页
    只有在使用通用视图或者视图集时,才会自动执行分页,如果使用APIView,则需要自己调用分页API以确保返回分页响应。
  2. 版本控制
    当启用 API 版本控制时,request.version 属性将包含对应于传入客户端请求中请求的版本的字符串。
 
  1. 测试
    创建测试请求:
1.from rest_framework.test import APIRequestFactory
2.
 
3.# 使用标准 RequestFactory API 创建表单 POST 请求
4.factory = APIRequestFactory()
5.request = factory.post('/notes/', {'title': 'new idea'})
  1. DRF中的认证流程
    共有三种方法
a. session认证
1.rest_framework.authentication.SessionAuthentication
b. jwt认证
json web token,服务器端无需保存token信息
1.rest_framework_jwt.authentication.JSONWebTokenAuthentication
jwt的加密方式
 
jwt和session cookies的不同
JWT 和 Session Cookies 都提供安全的用户身份验证,但是它们有以下几点不同
  • 密码签名
    JWT 具有加密签名,而 Session Cookies 则没有。
  • JSON 是无状态的
    JWT 是无状态的,因为声明被存储在客户端,而不是服务端内存中。
    身份验证可以在本地进行,而不是在请求必须通过服务器数据库或类似位置中进行。这意味着可以对用户进行多次身份验证,而无需与站点或应用程序的数据库进行通信,也无需在此过程中消耗大量资源。
  • 可扩展性
    Session Cookies 是存储在服务器内存中,这就意味着如果网站或者应用很大的情况下会耗费大量的资源。由于 JWT 是无状态的,在许多情况下,它们可以节省服务器资源。因此 JWT 要比 Session Cookies 具有更强的可扩展性。
  • JWT 支持跨域认证
    Session Cookies 只能用在单个节点的域或者它的子域中有效。如果它们尝试通过第三个节点访问,就会被禁止。如果你希望自己的网站和其他站点建立安全连接时,这是一个问题。
    使用 JWT 可以解决这个问题,使用 JWT 能够通过多个节点进行用户认证,也就是我们常说的跨域认证
c. 自定义,基于jwt、其他
继承BaseAuthentication(或其子类),必须重写authentication。
其中authentication中完成:
拿到认证标志 auth
反解析出用户 user
前两步操作失败 返回None => 优客
前两步操作成功 返回user, auth => 登录用户
具体流程
  1. 当用户进行登录的时候,运行了登录类的as_view()方法,进入了APIView类的dispatch方法
  2. 执行self.initialize_request这个方法,里面封装了request和认证对象列表等其他参数
  3. 执行self.initial方法中的self.perform_authentication,里面运行了user方法
  4. 再执行了user方法里面的self._authenticate()方法
    【ps.】以上是drf源码内容,下面为自定义方法
  5. 然后执行了自己定义的类中的authenticate方法,自己定义的类继承了BaseAuthentication类,里面有 authenticate方法,如果自己定义的类中没有authenticate方法会报错
  6. 把从authenticate方法得到的user和auth赋值给user和auth方法
  7. 这两个方法把user和auth的值分别赋值给request.user:是登录用户的对象;request.auth:是认证的信息字典
    具体可以查看APIView的源码,相关资料:关于DRF认证流程的相关资料
  8. 认证
    • 方法一
      系统:
      1)AllowAny:允许所有用户,校验方法直接返回True
      2)IsAuthenticated:只允许登录用户
      必须request.user和request.user.is_authenticated都通过
      3)IsAuthenticatedOrReadOnly:游客只读,登录用户无限制
      get、option、head 请求无限制
      前台请求必须校验 request.user和request.user.is_authenticated
      4)IsAdminUser:是否是后台用户
      校验 request.user和request.user.is_staff is_staff(可以登录后台管理系统的用户)
    • 方法二
      自定义:基于auth的Group与Permission表
      1)自定义权限类,继承BasePermission,重写has_permission
      2)has_permission中完成
      拿到登录用户 user <= request.user
      校验user的分组或是权限
      前两步操作失败 返回False => 无权限
      前两步操作成功 返回True => 有权限
流程
  1. 当用户执行一个业务的时候,运行了as_view方法,进入了APIView类的dispatch方法
  2. (此处不需要封装request了,因为在认证过程中封装了)
  3. 进入self.initial方法中的self.check_permissions(request)方法
  4. 里面执行了for循环,把每个权限类实例化对象

    以上是drf源码内容,下面为自定义方法

  5. 执行自己定义的权限类里面的has_permission方法,里面会判断request.user是否存在
  6. 不存在就返回False,存在就返回True
  7. 之后执行self.permission_denied报错方法,返回的是False就报错,可以自定义报错信息,在has_permission方法中写message = {“status”: False, “error”: “登录成功之后才能评论”},就实现了自定义报错
  8. 如果返回的是True就让他进入功能

WSGI

Python Web Server Gateway Interface,指定了web服务器和Python web应用或web框架之间的标准接口,以提高web应用在一系列web服务器间的移植性
  1. WSGI是一套接口标准协议/规范;
  2. 通信(作用)区间是Web服务器和Python Web应用程序之间;
  3. 目的是制定标准,以保证不同Web服务器可以和不同的Python程序之间相互通信
web服务器在将请求转交给web应用程序之前,需要先将http报文转换为WSGI规定的格式。
文章来自个人专栏
django学习
1 文章 | 1 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0