首页 > 其他分享 >drf-6

drf-6

时间:2022-10-08 18:23:03浏览次数:46  
标签:models self request 视图 token class drf

前5天内容小回顾

一、drf入门

  • 亲后端开发模式

    分离:drf方便我们快速写出接口

    混合:bbs、模板语法

  • API接口:前后端交互的媒介
  • 接口测试工具:postman(不止这一款)
  • restful规范
    1. 数据的安全保障:url链接一般都猜http协议进行传输 为了保证数据安全使用https协议传输      https指的是:   http  +   ssl/tsl
    2. 接口中带api关键词
    3. 多数据版本共存,一个接口可能有多个版本   url连接中标识版本标识    eg:假设有个登录接口:1.0只要用户名、密码 2.0要用户名、密码、验证码
    4. 数据即是资源,均使用名词(可用复数)---接口尽量使用名词    -都是用名词,没法区分是增加,删除,修改,查询
    5.  资源操作由请求方式决定
    6.  url地址中带过滤参数
    7. 响应带状态码
    8. 返回错误信息--->响应体中带错误信息    {code:100,msg:成功}
    9. 返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范
    10. 响应中带链接
  • drf快速入门
  • 必须继承APIView写视图类

    View的执行流程:cbv的执行流程

      -路由中:视图类.as_view()——本质是View的as_view内部的view闭包函数——dispatch——根据请求方式执行视图函数中得方法

    APIView的执行流程

      -as_view——本质是APIView的as_view:去掉csrf,调用父类的as_view

      -请求来了执行的是去掉了csrf认证后的View的as_view内的view闭包函数

      -self.dispatch——APIView

      -包装了新的request

      -执行三大认证

      -处理全局异常

  新的Request

    -包装了老的request    request._request

    -为了让咱们使用起来习惯一样:重写了__getattr__

    -data

    -query_params

    -文件,其他.......

二、序列化组件

  是怎么帮助我们快速实现【序列化】、【反序列化】、【数据校验】

  如何定义:

    1. 写一个序列化类继承(Serializer,ModelSerializer)
    2. 写要序列化的字段(字段类、字段参数:read_only,write_only)
    3. 字段自己的规则,局部钩子,全局钩子
    4. 序列化修改字段模式:

      -序列化类中写SerializerMethodField,get_字段名

      -表模型中写方法(返回字典,列表)

      -{“name”:"curry","age":33}——如果它是字符串   json格式字符串

      -{“name”:"curry","age":33}——如果它是字典      正常字典使用

      -{“name”:"curry","age":33}——如果它是字典  正常字典使用

      -{“name”:"curry","age":33}——如果它是字符串   不是json格式,json识别不了

  在视图类中使用

    -ser=BookSerializer(instance=要序列化的对象,many=True)

    -ser=BookSerializer(data=request.data)

    -ser=BookSerializer(instance=要修改的对象,data=request.data)

    -ser.data  字典格式

    -校验数据,   ser.errors

    -ser.save()  通过判断instance是否为空,决定调用的是create还是update

    -如果继承了Serializer,必须重写create和upate

  继承ModelSerializer写序列化类

    class meta:

      model=表模型

      fields='__all__'   【一定要注册一下 】

      extra_kwargs={'name':{read_only:True}}

    重写某个字段

    局部钩子全局钩子

    序列化修改字段格式跟之前一样

    一般不需要重写create和update

      一次性提交的数据可能涉及到多个表时

    注意:直接从表模型中映射的字段也有字段类和字段属性

三、请求与响应

  请求对象、响应对象(Request,Response)

  原生django响应头写内容

  drf能够解析的请求格式:局部配置和全局配置

  drf的响应格式:局部配置和全局配置

四、视图类

  -两个视图基类

    -APIView

    -GenericAPIView:属性或方法

      queryser = None

      serializer_class = None

      get_queryset()

      get_object()

      get_serializer()

  5个视图扩展类:需要配合GenericAPIView用

  9个视图子类:视图类,继承了GenericAPIView+5个视图扩展类之几+写个get、post、delete、put

  视图集

  -ViewSetMixin:重写了as_view,一旦继承了它及其子类,路由写法变了,as_view中加字典做映射

  -ViewSet=ViewSetMixin+APIView

    class TestView(ViewSet):

      def login(self,request):

  -GenericViewSet=iewSetMixin+GenericAPIView

    class TestView(GenercViewSet):

      queryset = None

      serializer_class = None

      def login(self,request)

  -ModelViewSet:路由写法变了,两个类属性queryset,serializer_class

  -ReadOnlyModelViewSet:路由写法变了,两个类属性queryset,serializer_class

以后到底要继承谁写视图类?

  -假设写获取所有图书

    -APIView

    -GenericAPIView

    -ListAPIView

 

五、路由

只有继承了ViewSetMixin及其子类的视图类

urls

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'})),
    path('books/<int:pk>', views.BookView.as_view({'get': 'list', 'post': 'create'})),
]

models

from django.db import models


# Create your models here.

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)


# 用户表
class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)

    def __str__(self):
        return self.username

views

class BookView(ModelViewSet):
    serializer_class = BookSerializer
    queryset = Book.objects.all()

第二种方式自动生成路由

"""def_7 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from app01 import views

# 自动生成路由
# drf提供了两个路由类,以后继承了ViewSetMixin及其子类的视图类,就可以使用这两个路由类来自动生成路由
# 使用步骤
# 第一步:导入路由类
from rest_framework.routers import SimpleRouter, DefaultRouter

# 第二步:实例化得到对象
router = SimpleRouter()  # 自动生成的路由后面要不要带/  默认是带/
# 第三步:注册路由(可以注册多个)
# 第一个参数:路径 第二个参数:视图类 第三个参数:别名 可以不写
router.register('books', views.BookView, 'books')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls)),
    # path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'})),
    # path('books/<int:pk>', views.BookView.as_view({'get': 'list', 'post': 'create'})),
]

# 第四步:把自动生成的路由器添加到urlpatterns中
# 第四步: 方式二、利用include添加path(‘’,include(router。urls)),
# urlpatterns += router.urls

DefaultRouter能访问根路径

SimpleRouter不能访问根路径  

小总结:

  只要是继承ViewSetMixin及其子类的视图后 路由写法可以自动生成

  第一步:导入路由类  from rest_framework.routers import SimpleRouter, DefaultRouter

  第二步:实例化得到对象  router = SimpleRouter()

  第三步:注册路由(可以注册多个) router.register('user',views.UserView,'user')

  第四步:把自动生成的路由器添加到urlpatterns中  (添加进去有两种方式,上面代码写的)

自动生成的路由映射关系其实定死了()
    /books/--->get--->list
    /books/--->post--->create
    /books/1--->get--->retrieve

以后写的视图类不需要写action装饰器的话,视图类中必须要有
    -list,destroy,retrieve,create,update方法之一
    -其实是必须是 5个视图扩展类之一+GenericAPIView   9个视图子类,ModelViewSet

action装饰器的使用

在视图函数中,会有一些其它名字的方法,必须要使用action装饰器做映射
    methods:支持的请求方式,列表
    detail:默认是False 控制生成的路由是  /user/login/ 还是 /user/pk/login    是不是带pk
    url_path: 控制生成的/user/后的路径是什么,如果不写,默认以方法名命名   /user/login/,一般跟函数名同名即可
    url_name:别名,用于反向解析
    
@action(methods=['GET','POST'], detail=True, url_path='login')
def login(self, request,pk):

# 这样写了以后可以:自动生成路由

六、登录接口编写

用户表

class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    def __str__(self):
        return self.username

用户登录记录表
如何区分用户是否登录了?

class UserToken(models.Model):
    # SET_NULL   SET_DEFAULT   CASCADE  SET(函数内存地址)
    user = models.OneToOneField(to='User', on_delete=models.CASCADE)
    token = models.CharField(max_length=32, null=True)  # 用户如果没有登录,就是空,如果登录了,就有值,登录多次以最后一次为准

views

class UserView(ViewSet):
    authentication_classes = []
    @action(methods=['POST', ], detail=False, url_path='login')
    def login(self, request):
        # 取出前端传入的用户名密码,校验,通过,返回登录成功,失败就返回用户名密码错误
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(username=username, password=password).first()
        if user:
            # 登录成功,不同人生成的token是不一样的,谁登录的,就把token存到UserToken表中
            token = str(uuid.uuid4())  # 生成一个永不重复的随机字符串
            # 存UserToken:如果没有记录,就是新增,如果有记录更新一下即可
            # 通过user去UserToken表中查数据,如果能查到,使用defaults的数据更新,如果查不到,直接通过user和defaults的数据新增
            UserToken.objects.update_or_create(defaults={'token': token}, user=user)
            return Response({'code': 100, 'msg': '登录成功', 'token': token})
        else:
            return Response({'code': 101, 'msg': '用户名或密码错误'})

urls.py

from rest_framework.routers import SimpleRouter, DefaultRouter

router = SimpleRouter()

router.register('user',views.UserView,'user')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls)),
]

七、认证

访问接口,必须登录后才能访问

  通过认证类完成,使用步骤
    1 写一个认证类,继承BaseAuthentication
    2 重写authenticate方法,在内部做认证
    3 如果认证通过,返回2个值
    4 认证不通过抛AuthenticationFailed异常
    5 只要返回了两个值,在后续的request.user 就是当前登录用户 
    6 如果想让某个视图类登录后才能访问
        -方式一:
            class BookView(ModelViewSet):
                authentication_classes = [LoginAuth,]
        -方式二:全局配置
            REST_FRAMEWORK={
            'DEFAULT_AUTHENTICATION_CLASSES':['app01.auth.LoginAuth',]
        }    
         -局部禁用:
            authentication_classes = []

认证类

from .models import UserToken
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 在这里做认证,校验用户是否登录(带了token,并且能查到,就是登录,返回两个值,否则就是没登录,抛异常)
        # 用户带的token从哪取?后端人员定的:放在请求地址中
        token = request.GET.get('token')
        # 通过token查询该token是否是在表中有记录
        user_token = UserToken.objects.filter(token=token).first()
        if user_token:
            return user_token.user, token  # 返回两个值,一个是当前登录用户,一个是token
        else:
            raise AuthenticationFailed('您没有登录')

八、作业

1 登录接口,图书5个接口,出版社5个接口(关联的关系),,使用9个视图子类,5个视图扩展类写
2 图书的必须登录后才能方法,出版社的不登录就能访问
    -全局配置,局部禁用

class BookView(ListCreateAPIView):
    # authentication_classes = [LoginAuth]
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookSerializer


class BookDetailView(RetrieveUpdateDestroyAPIView):
    # authentication_classes = [LoginAuth]
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookSerializer


class PublishView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = models.Publish.objects.all()
    serializer_class = serializer.PublishSerializer
    authentication_classes = []

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class PublishDetailView(GenericAPIView, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin):
    queryset = models.Publish.objects.all()
    serializer_class = serializer.PublishSerializer
    authentication_classes = []

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

3.级联删除小知识

on_delete=None, # 删除关联表中的数据时,当前表与其关联的field的行为 on_delete=models.CASCADE, # 删除关联数据,与之关联也删除 on_delete=models.DO_NOTHING, # 删除关联数据,什么也不做 on_delete=models.PROTECT, # 删除关联数据,引发错误ProtectedError # models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True) on_delete=models.SET_NULL, # 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理) # models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值') on_delete=models.SET_DEFAULT, # 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理) on_delete=models.SET, # 删除关联数据, a. 与之关联的值设置为指定值,设置:models.SET(值) b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

标签:models,self,request,视图,token,class,drf
From: https://www.cnblogs.com/zzjjpp/p/16768958.html

相关文章

  • drf之路由类与认证类
    一、自动生成路由对于我们的视图类只要继承了ViewSetMixin及其子类那么路由的写法就需要改变path('books/',views.BookView.as_view({'get':'list'}))这个时候有人写......
  • drf_1~5
    前后端开发模式1.前后端不分离----全栈涉及模板语法2.前后端分离2.1前端测试工具:模仿发送http请求--postman2.2api接口:连接前后端的媒介restful规范1.使用https......
  • drf05-2个视图基类-5个扩展类-9个视图子类-视图集
    1.2两个视图基类#之前写了五个接口,继承APIView#还可以继承GenericApiView:它帮了我们干很多事#GeneriaAPIView.属性和方法-属性 -queryset#要序列化的数据 -seri......
  • drf视图基类,视图扩展类和视图子类
    两个视图基类GenericAPIView属性: queryset#要序列化的数据 serializer_class#序列化类#了解lookup_field#通过get_object......
  • drf学习-5
    drf视图继承关系表2个视图基类之前写5个接口,继承了APIview还可以继承GenericAPIView,它帮我们干了好多事GenericAPIView:属性和方法属性  掌握项  -queryset......
  • drf从入门到精通
    前后端开发模式API接口、接口测试工具postman、restful规范、序列化与反序列化、djangorestframework快速使用rest-framework之APIView基本使用及源码分析、Request类源......
  • 【2022-09-30】DRF从入门到入土(五)
    DRF视图继承关系表链接https://www.processon.com/embed/60dec4091e085359888e3e722个视图基类#之前写的5个接口,我们都是继承APIView#还可以继承GenericAPIView:它......
  • drf之视图集
    一、试图基类#我们之前学习的drf在编写视图类的时候是继承了APIView和GenericAPIView#GenericAPIView的属性和方法回顾:-属性-queryset#要......
  • drf学习笔记
    今日内容概要两个视图基类五个视图扩展类九个视图子类视图集今日内容详细两个视图基类补充:GenericAPIView:属性:1.queryset#要序列化的数据......
  • drf-04
    目录请求与响应请求Request响应Response视图组件视图的继承2个视图基类drf内容框架作业请求与响应请求Request1.request:drf中的request不再是django默认的HttpRequest对......