4-1 请求和响应-DRF请求和响应

目录:

  • DRF请求和响应介绍
  • 装饰器视图 @api_view(['GET','POST'])
  • 类视图:APIView

一、DRF请求和响应

请求和响应:

  目前我们用的都是Django 里面的 request、也是Django 里面的 response,状态也是django里面的。但是 DRF里面的 request是基于 django 里面的 request 进行的封装。

请求(request):

  REST里面有个HttpRequest特别相似的对象叫request,主要获取前端传递过来的数据,获取数据的方法就是request.data

响应(Response):

  REST里面有个HttpResponse特别相似的对象叫Response,主要用来给前端传递数据,传递数据的方法就是Response(data)

状态码(status):

  REST里面的状态码比较人性化。每个状态都用意思去表示。比如:

HTTP_200_OK = 200 #OK
HTTP_201_CREATED = 201 #创建成功
HTTP_403_FORBIDDEN = 403 # 权限拒绝
'''
'''

API视图:

  API视图主要为了咱们RESTFUL风格的API。主要用来包装request,response、现在api请求方法。

  • 基于函数视图的@api_view(['GET','POST'])装饰器
  • 基于类视图的APIView

二、装饰器视图 @api_view(['GET','POST'])

我们根据 DRF 提供我们的 api_view、Response、status、request 来重写我们的视图函数

from .serializers import UserSerializer
from .models import User
from rest_framework.decorators import api_view
from rest_framework.response import Response  #提供drf的响应
from rest_framework import status  #提供DRF状态码


@api_view(['GET', 'POST'])  #首先告诉它支持哪些方法,而且装饰之后不需要crf_token验证,因为api_view已经帮我们做了验证
def user_list(request): #用了api_view装饰器之后,这边的request就已经是DFR的request了。
    if request.method == "GET":
        arts = User.objects.all()
        ser = UserSerializer(instance=arts, many=True, context={'request': request})
        return Response(ser.data, status=status.HTTP_200_OK)  #直接把序列化数据很状态码传入进去
    elif request.method == "POST":
        #获取入参直接是 request.data 即可获取
        ser = UserSerializer(data=request.data, context={'request': request})
        if ser.is_valid():
            ser.save()
            return Response(ser.data, status=status.HTTP_201_CREATED)
        return JSONResponse(ser.errors, status=status.HTTP_401_UNAUTHORIZED)

知识点说明:

@api_view(['GET', 'POST']):
    1.告诉它需要支持哪些方法:这边支持POST和GET
    2.装饰完api_view,不在需要crf_token验证了,因为api_view已经帮你封装好了
    3.用了api_view装饰器之后,request就已经是DRF的request了,不再是 django的 request了 => 调用直接 request.data

drf的响应:from rest_framework.response import Response => Response(data,status=status.HTTP_201_CREATED)
 
提供DRF状态码:from rest_framework import status  => status.HTTP_201_CREATED

我们通过页面来访问一下:(当然也可以通过postman访问)

 

三、类视图:APIView

我们还有一种方法,可以通过 类视图:APIView,功能跟我们的 @api_view 一样,只不过采用的是CBV的方式

3.1、视图

说明:编辑views.py文件,增加视图类

from .serializers import UserSerializer
from .models import User

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status

from rest_framework.views import APIView #提供类视图
from django.http import Http404 #提供django的404状态码


@api_view(['GET', 'POST']) 
def user_list(request): 
    ...

class UserDetail(APIView): #采用类视图,定义 get、patch、put和delete

    def get_object(self, id):
        try:
            user = User.objects.get(id=id)
            return user
        except User.DoesNotExist as e:
            return Http404

    def get(self,request, *args, **kwargs):
        user = self.get_object(kwargs.get('id'))   #根据传值 **kwargs获取id的值
        ser = UserSerializer(instance=user,context={"request": request})
        return Response(ser.data, status=status.HTTP_200_OK)

    def put(self, request, *args, **kwargs):
        user = self.get_object(kwargs.get('id'))
        ser = UserSerializer(instance=user,data=request.data, context={"request": request})  #request是drf的了,所以获取数据request.data
        if ser.is_valid():
            ser.save()
            return Response(ser.data, status=status.HTTP_201_CREATED)
        return Response(ser.errors, status=status.HTTP_400_BAD_REQUEST)

    def patch(self, request, *args, **kwargs):
        user = self.get_object(kwargs.get('id'))
        ser = UserSerializer(instance=user, data=request.data, context={"request": request},partial=True)
        if ser.is_valid():
            ser.save()
            return Response(ser.data, status=status.HTTP_201_CREATED)
        return Response(ser.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, *args, **kwargs):
        user = self.get_object(kwargs.get('id'))
        user.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

3.2、路由配置

说明:因为我们是采用CBV的方式,所以路由的方式要改变

from django.urls import path
from app03 import views


urlpatterns = [
    path("user/", views.user_list, name="user-list"),  #FBV的方式
    path("user/<int:id>/", views.UserDetail.as_view(), name="user-detail")  #cbv方式 => views.UserDetail.as_view()
]

这边还有一个地方需要注意:就是我们前面讲的,在输入 pwd1验证的时候,因为pwd1不属于 User模型类字段,所以我们需要 pop掉,但是这边会报错,所以我们代码优化如下:

编辑 serializers.py文件:

....

class UserSerializer(serializers.ModelSerializer):
    ....

    class Meta:
        ....

    def validate_phone(self, phone):  #单个验证
       ...

    def validate(self, attrs): #组合验证
        if attrs.get('pwd1') != attrs.get('pwd'):
            raise serializers.ValidationError("两次密码不一样")
        if "pwd1" in attrs:  #这边需要加一个验证,当我通过patch传进来的时候,没有pwd1的参数,则我不删除
            attrs.pop('pwd1')
        return attrs

3.3、运行结果

1、页面访问:

 

 

2、postman请求:

1.GET: http://127.0.0.1:8000/api/user/1/

出参:
{
    "id": 1,
    "phone": "13641929921",
    "name": "gaogao",
    "gender": 1
}

2.POST:http://127.0.0.1:8000/api/user/

入参:
{
    "phone": "13641929930",
    "gender": 2,
    "name": "gaogao",
    "pwd": "1234",
    "pwd1": "1234"
}

出参:
{
    "id": 6,
    "phone": "13641929930",
    "name": "gaogao",
    "gender": 2
}

3.PUT:http://127.0.0.1:8000/api/user/1/
入参:
{
    "id": 1,
    "phone": "13641929923",
    "name": "gaogege",
    "gender": 1,
    "pwd": "1234",
    "pwd1": "1234"
}

出参:
{
    "id": 1,
    "phone": "13641929923",
    "name": "gaogege",
    "gender": 1
}

4.PATCH: http://127.0.0.1:8000/api/user/1/
入参:
{
    "id": 1,
    "phone": "13641929924",
    "gender": 2

}

出参:
{
    "id": 1,
    "phone": "13641929924",
    "name": "gaogege",
    "gender": 2
}

5、DELETE:http://127.0.0.1:8000/api/user/1/

出参:
[]

 

posted @ 2020-04-27 10:42  帅丶高高  阅读(613)  评论(0)    收藏  举报