drf学习总览,http请求不同编码格式,请求体什么样子,新的Request对象和Response, 序列化类,反序列化保存

Ⅰ drf学习总览概述

# 1 请求和响应
    request:请求对象:请求方式,请求携带的数据,request.GET,request.POST,requset.body,request.META:请求头中得
    四件套:操作响应体
        HTTPResponse('sdfs')  # 若是要携带请求头和响应状态码  应该是 return HTTPResponse('sdfs', status=201, headers={"xx":"yy"})
        JsonResponse(字典列表)
        render(request,模板文件)
        
    drf有自己的请求和响应
        request
        Response 的对象
            
# 2 序列化类:Serializer  用途
        1.做序列化
        2.做反序列化的
        3.反序列化的校验
        
# 3 视图类:drf提供了非常多 视图类可以继承
# 4 路由
# 5 认证:登录认证
# 6 权限
# 7 频率限制
# 9 统一返回错误
# 10 jwt:登录认证用
# 11 基于角色的访问控制

Ⅱ http请求不同编码格式,请求体什么样子

【一】get请求能不能再请求体中携带数据?

能
一般都是post或put请求在请求体中带数据

【二】get请求和post请求区别?

GET:主要用于获取服务器上的资源。GET请求通常用于查询数据,不应当引起服务器上的任何状态变化。
POST:主要用于向服务器发送要被处理的数据(例如,表单数据、文件上传等)。

GET:由于数据附加在URL中,因此GET请求的数据大小受到URL长度限制,通常限制在1024字节左右。
POST:数据包含在请求体中,理论上没有大小限制,可以发送大量数据。相对更安全

总结来说,GET请求更适合用于获取数据,而POST请求更适合用于发送数据

【三】总结

django视图类或视图函数的request
        request.POST:只针对于 post请求的urlencoded编码格式 才有数据 # 重点
        request.GET:请求地址栏中得参数:get,post,delete,put
        	# <QueryDict: {'key': ['key', '99']}>
            类字典:取出key的值
                只取一个:request.GET.get('key')
                两个都取:request.GET.getlist('key')
        request.body:无论什么请求, 无论什么编码格式,都在里面
        
http不同编码格式
    	urlencoded:在请求体中是  key=value&key=value
        json:在请求体中是  {"name":"lqz","age":19}
        form-data: asdfasdf-------数据部分  asdfasdfasdf-----文件部分
  • form-data请求体编码格式如下图

Ⅲ 新的Request对象和Response

【一】 Request

# 1  以后全是cbv,继承一个基类--> drf的APIView【也继承了Django的View】及子类
# 2 继承APIView后, 以后响应统一用 drf的响应  : Response

# !!!!!!!  如果想用 Response 要在 settings里面 将 rest_framework 放进去  否则会报错

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'app01.apps.App01Config',
    'rest_framework',
]

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.views import View
from rest_framework.request import Request


class BookView(APIView):
    def get(self, request):
        '''
        1 request 请求对象:http请求的所有内容,都会在这个对象中
        2 继承APIView后的request对象,不是之前的request对象了
             原来的:django.core.handlers.wsgi.WSGIRequest
             新的: rest_framework.request.Request
        3 用起来跟之前一样
            print(request.method)
            print(request.POST)
            print(request.GET)
            print(request.get_full_path())
        4 request.data
            无论那种编码格式,请求体的数据,都在这里面
                urlencoded,form-data:是QueryDict的对象
                json:是普通字典对象
                但是,都当字典用即可
        5 request.FILES
            前端传的文件从这里取
        6 request.query_params # 查询参数
            request.GET

        7 老的request在
            requset._request
        '''
        # print(type(request))
        # print(request.method)
        # print(request.POST)
        # print(request.GET)
        # print(request.get_full_path())

        print(request.data)
        print(request.query_params)
        print(request._request)

        # return JsonResponse({'code':100,'msg':'请求成功'})
        # 如果使用postman访问,返回json,如果使用浏览器访问,会返回好看的样式界面,使用Response必须注册app
        return Response('ok', status=status.HTTP_404_NOT_FOUND, headers={'xx': 'yy'})

【二】Response

from rest_framework.response import Response

【1】如何用

直接放字典,列表或字符串 
Response('ok')
    	放在响应体中了

【2】如何放状态码

Response('ok',status=201)

【3】如何放响应头

Response('ok',status=201,headers={'xx':'yy'})

【4】总结 Response

data=None # 响应体:可以传 字典,列表或字符串
status=None# http响应 状态码-->drf封装了所有常量   HTTP_200_OK = 200    从from rest_framework import status看    CTRL加鼠标右键  点击status看
template_name=None# 忽略掉-->指定使用浏览器访问返回的模板,没写用默认模板
headers=None # 响应头           
exception=False# 异常
content_type=None # 响应编码格式,一般不动,都用json
  • template_name=None
  • 在源码中看,最后是好看的模板样式
  • 如果使用postman访问,返回json,如果使用浏览器访问,会返回好看的样式界面

Ⅳ 序列化类

【一】序列化类介绍

# 序列化类的作用
	前端传json格式字符串 给 后端 -->后端需要 保存到数据库--->   这就需要反序列化
    后端从数据库查出来的 对象--->以json格式字符串的形式给前端-->  这就需要序列化
    
    serializer就是为了完成上面的操作
    	序列化
        反序列化
        反序列化校验

【二】快速使用

  • app下的models.py
from django.db import models


class Student(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    gender = models.IntegerField(choices=((1, '男'), (2, '女'), (0, '未知')))
  • 先进行路由分发
from django.urls import path,include

urlpatterns = [

    path('api/v1/', include('app01.urls')),
]
  • app下的路由urls.py
from .views import BookView,BookDetailView,StudentView,StudentDetailView
from django.urls import path


urlpatterns = [
    path('students/', StudentView.as_view()),
    path('students/<int:pk>/', StudentDetailView.as_view()),
]
  • app下的views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
import json
from django.http import JsonResponse, HttpResponse

from .serializer import StudentSerializer
from .models import Student

# 查询所有数据
class StudentView(APIView):
    def get(self,request):
        # 查出所有学生
        # 得到的是 queryset对象
        result = Student.objects.all()

        # 序列化
        # 第一种方法
        # 序列化 -->笨办法 -->自己拼接,麻烦一些
        # lli=[]
        # for student in result:
        #     lli.append({'id':student.pk,'name':student.name,'age':student.age,'gender':student.get_gender_display()})

        # 第二种
        # 2 drf提供的序列化类完成序列化:instance要序列化的对象,如果是多条 many=True
        serializer = StudentSerializer(instance=result, many=True)



        # 返回
        # return JsonResponse(result,safe=False)  # Object of type QuerySet is not JSON serializable
        # return Response(result)   # no such table: app01_student 这个报错是由于还没有迁移数据库
        # return Response(result)   # Object of type Student is not JSON serializable
        return Response(serializer.data)
    
    
# 查询单条数据
class StudentDetailView(APIView):
    def get(self, request, pk):
        # 1 根据id查出对象
        obj = Student.objects.filter(pk=pk).first()
        # 2 序列化
        serializer = StudentSerializer(instance=obj)
        # 3 返回
        return Response(serializer.data)

  • app下serializer.py
from rest_framework import serializers

'''
使用步骤:
    1 定义一个类,继承Serializer
    2 在类中写要序列化的字段:字段类,跟models中得一一对应
    3 在视图类中使用
'''

from .models import Student
class StudentSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    name = serializers.CharField(required=True)    # 不想在postman上展示那个字段 只需要注销即可
    age = serializers.IntegerField(required=True)
    gender = serializers.IntegerField(required=False,default=0)

【三】常用字段

#  记住-->跟models中得 model.字段类, 一一对应
#  具体有哪些-->了解
# 常用的一些字段 用# 标记出
BooleanField
NullBooleanField	
CharField  # 	
EmailField	
RegexField	
SlugField	
URLField	
UUIDField	
IPAddressField
IntegerField	  #  
FloatField
DecimalField	
DateTimeField  # 	
DateField	  #
TimeField	  #
ChoiceField	
MultipleChoiceField	
FileField	
ImageField	
# --------两个特殊的,很重要----
ListField
DictField	
#  大绝招:如果不知道models和Serializer如何对应
	序列化类统一用 CharField 

【四】 常用字段参数

#  序列化的 字段类在实例化时,传参数
	-作用是:为了反序列化校验用
    
#  有哪些字段参数-->了解
	# 只针对于:CharField
	max_length	最大长度
    min_lenght	最小长度
    allow_blank	是否允许为空
    trim_whitespace	是否截断空白字符
    
    # 只针对于:IntegerField
    max_value	最小值
    min_value	最大值
    
    # 只针对于:DateTimeField 
    format:序列化时,显示的格式
    DateTimeField(format='Y-m-d')
    或者  DateTimeField(format='Y/m/d')...
    # 所有字段类都用
    required:是否必填	
    default	:反序列化时使用的默认值
    allow_null	表明该字段是否允许传入None,默认False

    
#  两个重点
    read_only	表明该字段仅用于序列化输出,默认False
    write_only	表明该字段仅用于反序列化输入,默认False

Ⅴ 反序列化保存

【一】新增

#  使用步骤:
    1. 写个序列化类,继承Serializer
    2. 在序列化类中写字段,和字段参数[校验用的]
    3. 在视图类中使用
    	    def post(self, request):
        # 1 取出前端传入的数据-->无论什么编码格式,无论什么请求方式    request.data
        serializer = StudentSerializer(data=request.data)
        # 2 反序列化校验,保存到数据库
        if serializer.is_valid():
            # 校验通过,保存,会报错,    所以在序列化类中重写create方法
            serializer.save()
            # 3 返回给前端成功
            # return Response(serializer.data) # 把新增的数据,序列化一下,返回
            return Response({'code': 100, 'msg': '保存成功'})
        else:
            # 4 返回给前端失败
            return Response({'code': 101, 'msg': '数据校验失败'})
    4.要在序列化类中重写create
      def create(self, validated_data):
        # validated_data:前端传入,校验过后的数据
        student=Student.objects.create(**validated_data)
        return student # 不要忘了,返回新增的对象--->后期调用serializer.data 时,会使用它序列化

【二】修改

#  使用步骤:
    1. 写个序列化类,继承Serializer
    2. 在序列化类中写字段,和字段参数[校验用的]
    3. 在视图类中使用
    def put(self, request, pk):
        # 1 查出要修改的对象
        obj = Student.objects.filter(pk=pk).first()
        # 2 拿到前端传入的数据--修改成的数据
        serializer = StudentSerializer(instance=obj, data=request.data)
        # 3 校验数据是否合法
        if serializer.is_valid():
            # 4 修改   在序列化类中重写 update
            serializer.save()

            return Response({'code': 100, 'msg': '修改成功'})
        else:
            # 4 返回给前端失败
            return Response({'code': 101, 'msg': '修改失败,因为数据校验失败'})

    4.要在序列化类中重写update
      def update(self, instance, validated_data):
        # validated_data:前端传入,校验过后的数据
        # instance:待修改的对象
        # 1 笨办法
        # instance.name=validated_data.get('name')
        # instance.age=validated_data.get('age')
        # instance.gender=validated_data.get('gender')
        # 2 高级办法
        for key in validated_data: # 循环拿到字典的一个个key
            # 等同于 instance.name=validated_data.get('name')
            setattr(instance,key,validated_data.get(key))

        instance.save()
        return instance #不要忘了,返回修改的对象--->后期调用serializer.data 时,会使用它序列

【三】源码

# 1 为什么要重写 update和create
	因为执行serializer.save--->会触发self.create或self.update执行
    我们没写-->找父亲-->找父亲-->找到了
    def create(self, validated_data):
        raise NotImplementedError('`create()` must be implemented.')
# 2 为什么调用的都是save,但是最后触发的序列化类中得方法是不同的?
	因为内部判断了 instance 是否为None

# 阅读源码
	serializer.save()-->序列化类对象【自己写的StudentSerializer,没有save】 调用save,会触发父类的save-->Serializer中也没有save--->继续找父类BaseSerializer 有save方法
    save源码
    	# self 是咱们写的序列化类的对象
        # 如果是修改,instance 有值
        if self.instance is not None:
            # self.update 自己重写了,调用自己的
            self.instance = self.update(self.instance, validated_data)
        else:
            self.instance = self.create(validated_data)
        return self.instance

posted on   silence^  阅读(25)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示