drf基础

1. 序列化过程

子应用里面的路由

from django.urls import path, re_path
from . import views

urlpatterns = [
    path("student/", views.StudentView.as_view())
]

总路由

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("student/",include("students.urls")),
    path("sers/",include("sers.urls")),
]

模型类

from django.db import models

# Create your models here.
class Student(models.Model):
    # 表字段声明
    # 字段名=models.数据类型(字段约束)
    name = models.CharField(null=False, max_length=32, verbose_name="姓名")
    sex  = models.BooleanField(default=True, verbose_name="性别")
    age  = models.IntegerField(verbose_name="年龄")
    class_num = models.CharField(max_length=5, verbose_name="班级编号")
    description = models.TextField(max_length=1000, verbose_name="个性签名")

    # 表信息
    class Meta:
        # 设置表名
        db_table="tb_students"
        verbose_name="学生"
        verbose_name_plural=verbose_name

    # 模型的操作方法
    def __str__(self):
        return self.name

定义的序列化器

from rest_framework import serializers


class StudentSerializers(serializers.Serializer):

    name = serializers.CharField()
    age = serializers.IntegerField()
    sex = serializers.BooleanField()

视图

from django.views import View
from django.http.response import JsonResponse, HttpResponse

from .serializers import StudentSerializers
from students import models

class StudentView(View):
    def get(self, request):
        # student_list = models.Student.objects.all()
        student_list = models.Student.objects.filter(pk=1)
        serializer = StudentSerializers(instance=student_list, many=True)
        print(serializer.data)
        return HttpResponse("ok")

2. 反序列化过程

子应用里面的路由

from django.urls import path, re_path
from . import views

urlpatterns = [
    path("student/", views.StudentView.as_view())
]

反序列化器以及校验方法

from rest_framework import serializers
from students import models

# 字段验证函数[只能用于验证一个字段数据]
def check_class_num(data):
    if data == "88888":
        print(data)
        raise serializers.ValidationError("一边去,小庙容不下您")
    return data

class StudentSerializers(serializers.Serializer):
    name = serializers.CharField(max_length=20, required=True)
    age = serializers.IntegerField(max_value=120, required=True)
    sex = serializers.BooleanField(default=1)
    class_num = serializers.CharField(required=True, validators=[check_class_num])
    description = serializers.CharField(allow_null=True, allow_blank=True)

    # 字段验证方法
    # validate_字段名()   # 验证单个字段
    # validate()         # 验证所有字段
    def validate_name(self, attr):
        exists = models.Student.objects.filter(name=attr).exists()
        if exists:
            raise serializers.ValidationError("姓名不能重复")
        # 注意,每次验证完成以后必须有结果返回!否则数据就会丢失
        return attr

    def validate(self, attrs):
        if attrs.get("name") == "乾隆" and attrs.get("sex") == True:
            raise serializers.ValidationError("别闹")
        return attrs


    # 数据校验成功后进行保存
    def create(self, validated_data):
        ret = models.Student.objects.create(**validated_data)
        return ret

    # 更新数据
    def update(self, instance, validated_data):
        # instance.name = validated_data.get("name")
        # instance.age = validated_data.get("age")
        # instance.sex = validated_data.get("sex")
        # instance.class_num = validated_data.get("class_num")
        # instance.description = validated_data.get("description")
        # 简便写法
        for key, value in validated_data.items():
            setattr(instance, key, value)

      instance.save()
      return instance

视图

import json
from django.views import View
from .serializers import StudentSerializers
from django.http.response import HttpResponse, JsonResponse

from students import models

class StudentView(View):
    # 提交数据
    def post(self, request):
        data = json.loads(request.body)
        # print(data)
        # {'name': 'bob', 'sex': True, 'age': 13, 'class_num': '303', 'description': '张三怕李四'}
        serializer = StudentSerializers(data=data)
        ret = serializer.is_valid(raise_exception=True)
        # print(serializer.validated_data)
        # OrderedDict([('name', 'bob'), ('age', 13), ('sex', True), ('class_num', '303'), ('description', '张三怕李四')])
        # print(serializer.errors)

        serializer.save()
        return HttpResponse("ok")

    # 更新
    def put(self, request):
        # 接收客户端提交的修改数据并获取要更新字段的模型对象
        data = json.loads(request.body)
        pk = data.get("id")
        obj = models.Student.objects.filter(pk=pk).first()
        # partial=True表示设置值验证客户端上传来的部分数据,没有上传的字段,即便有选项或者验证方法,也忽略不管.
        serializer = StudentSerializers(instance=obj, data=data, partial=True)
        serializer.is_valid(raise_exception=True)
        """
        serializer.save()之所以会自动判断什么时候执行create或者update,
        原因是save内部中根据实例化序列化器时是否传递模型对象参数(instance)进来而判断的.
        """
        serializer.save()
        return HttpResponse("更新成功")

    # 获取数据
    def get(self, request):
        obj = models.Student.objects.filter(pk=1).first()
        serializer = StudentSerializers(instance=obj)
        return JsonResponse(serializer.data, json_dumps_params={"ensure_ascii": False})

3. 模型类序列化器

ModelSerializer与常规的Serializer类似,但提供了以下功能:

  • 基于模型类自动生成一系列序列化器字段

  • 基于模型类自动为Serializer生成validators,比如unique_together

  • 包含默认的create()和update()的实现

子应用中的路由

from django.urls import path, re_path
from . import views

urlpatterns = [
    path("student/", views.StudentView.as_view()),
    path("student2/", views.Student2View.as_view())
]

模型类序列化器

# 模型类序列化
class StudentModelSerializers(serializers.ModelSerializer):
    # 字段声明
    token = serializers.CharField(max_length=128, read_only=True, default="123")
    # 序列化器中也可以转换自定义的字段

    # 模型声明
    class Meta:
        model = models.Student
        fields = ["id","name","age","sex", "token"]
        # fields = "__all__" # 调用模型所有字段
        read_only_fields = ["id"]
        # read_only_fields 表示设置模型中那些字段属于只读类型的,对于不在模型中字段无效

        # 我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
        extra_kwargs = {
            "token": {"read_only": True},
            "age": {"min_value": 0, "max_value": 120}
        }

视图

class Student2View(View):
    def get(self, request):
        obj = models.Student.objects.filter(pk=1).first()
        serializer = StudentModelSerializers(instance=obj)
        return JsonResponse(serializer.data, json_dumps_params={"ensure_ascii": False})

    def post(self, request):
        data = json.loads(request.body)
        serializer = StudentModelSerializers(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return JsonResponse(serializer.data, json_dumps_params={"ensure_ascii": False})
  ...

4. 请求和响应

4.1 request: 

REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。[在drf中,原生的django的http请求对象,通过request._request]

REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典[QueryDict]对象保存到Request对象中。

Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。

无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。

data属性: 

request.data 返回解析之后的<mark>请求体</mark>数据。类似于Django中标准的`request.POST`和 `request.FILES`属性,但提供如下特性:

- 包含了解析之后的文件和非文件数据
- 包含了对POST、PUT、PATCH请求方式解析后的数据
- 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据

相当于drf的request.data替代了 django的request.POST,request.FILES,request.body、

query_params属性

request.query_params返回解析之后的<mark>查询字符串</mark>数据

request.query_params与Django原生的request.GET相同,只是更换了更正确的名称而已。

4.2 Reponse: 

rest_framework.response.Response

REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(renderer渲染器)成符合前端需求的类型。

REST framework提供了Renderer 渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。【简而言之,就是Renderer能通过请求找的Accept查询出客户端支持和希望的数据类型,把视图的结果以客户端能识别的格式返回】

可以在rest_framework.settings.py查找所有的drf默认配置项

参数说明:

- `data`: 为响应准备的序列化处理后的数据;
- `status`: 状态码,默认200;
为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量。
- `template_name`: 模板名称,如果使用`HTMLRenderer` 时需指明; - `headers`: 用于存放响应头信息的字典; - `content_type`: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。

5. REST framework 中提供的视图

子应用中的urls.py

from django.urls import path, re_path
from . import views

urlpatterns = [
    path("student/", views.StudentAPIView.as_view()),
    re_path("^student2/(?P<pk>d+)/$", views.Student2APIView.as_view())
]

serializers.py

from rest_framework import serializers
from students import models

class StudnetModelSerializers(serializers.ModelSerializer):

    class Meta:
        model = models.Student
        fields = "__all__"


class Studnet2ModelSerializers(serializers.ModelSerializer):

    class Meta:
        model = models.Student
        fields = ["id", "name"]

views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from students import models
from .serializers import StudnetModelSerializers

class StudentAPIView(APIView):
    def get(self, request):
        obj_list = models.Student.objects.all()
        serializer = StudnetModelSerializers(instance=obj_list, many=True)
        return Response(serializer.data)

    def post(self, request):
        data = request.data  # 直接用request.data接收数据
        serializer = StudnetModelSerializers(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

class Student2APIView(APIView):
    def put(self, request, pk):
        obj = models.Student.objects.filter(pk=pk).first()
        data = request.data
        serializer = StudnetModelSerializers(instance=obj, data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    def get(self, request, pk):
        print(111)
        obj = models.Student.objects.filter(pk=pk).first()
        serializer = StudnetModelSerializers(instance=obj)
        return Response(serializer.data)

    def delete(self, request, pk):
        models.Student.objects.filter(pk=pk).delete()
        return Response("删除成功", status=status.HTTP_200_OK)

6. GenericAPIView :

通用视图类主要作用就是把视图中的独特的代码抽取出来,让视图方法中的代码更加通用,方便把通用代码进行简写。继承自APIView, 主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。

属性:
serializer_class 指明视图使用的序列化器
queryset 指明使用的数据查询集


方法: 
get_serializer_class(self):
当出现一个视图类中调用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中通过返回不同的序列化器类名就可以让视图方法执行不同的序列化器对象了。
返回序列化器类,默认返回`serializer_class`,可以进行改写

get_serializer(self, *args, **kwargs):
返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。
注意,该方法在提供序列化器对象的时候,会向序列化器对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。
- request 当前视图的请求对象
- view 当前请求的类视图对象
- format 当前请求期望返回的数据格式

get_queryset(self): 
返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以进行改写

get_object(self):
返回单个视图模型类对象,主要用来提供给Mixin扩展类使用。
在试图中可以调用该方法获取详情信息的模型类对象。
若详情访问的模型类对象不存在,会返回404。
该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。

urls.py

from django.urls import path, re_path
from . import views

urlpatterns = [
    path("student/", views.StudentGenericAPIView.as_view()),
    re_path("^student2/(?P<pk>d+)/$", views.Student2GenericAPIView.as_view()),
    path("student3/", views.Student3APIView.as_view()),
    re_path("^student4/(?P<pk>d+)/$", views.Student4APIView.as_view()),
]

serializers.py:

from rest_framework import serializers
from students import models

class StudnetModelSerializers(serializers.ModelSerializer):

    class Meta:
        model = models.Student
        fields = "__all__"


class Studnet2ModelSerializers(serializers.ModelSerializer):

    class Meta:
        model = models.Student
        fields = ["id", "name"]

views.py

from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status
from demo.serializers import StudnetModelSerializers, Studnet2ModelSerializers
from students import models


class StudentGenericAPIView(GenericAPIView):
    queryset = models.Student.objects

    def get_serializer_class(self):
        if self.request.method.lower() == "get":
            return Studnet2ModelSerializers
        else:
            return StudnetModelSerializers

    def get(self, request):
        serializer = self.get_serializer(instance=self.get_queryset(), many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

class Student2GenericAPIView(GenericAPIView):
    serializer_class = StudnetModelSerializers
    queryset = models.Student.objects

    def put(self, request, pk):
        data = request.data
        # serializer = self.serializer_class(instance=self.queryset.filter(pk=pk).first(), data=data)
        serializer = self.get_serializer(instance=self.get_object(), data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    def get(self, request, pk):
        # serializer = self.serializer_class(instance=self.queryset.filter(pk=pk).first())
        serializer = self.get_serializer(instance=self.get_object())
        return Response(serializer.data)

    def delete(self, request, pk):
        self.queryset.filter(pk=pk).delete()
        return Response("删除成功",status=status.HTTP_200_OK)
原文地址:https://www.cnblogs.com/fdsimin/p/13604165.html