Ⅰ 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
标签:序列化,请求,request,instance,总览,data,Response
From: https://www.cnblogs.com/zyb123/p/18324159