【一】补充知识
【1】http中get请求能不能再请求体中携带数据
-
可以,但是一般都是post和put请求
【2】get请求与post请求的区别
-
首先post请求比get请求更安全
-
POST请求:可以发送多种类型的数据,包括文本、图片、音频、视频等
-
GET请求:只能发送ASCII字符,不支持发送二进制数据或大量文本数据
# GET请求:通常用于请求从服务器获取数据,是一个幂等的请求。幂等性意味着对资源的同一GET请求多次执行,返回的结果应该相同且不会对资源产生副作用(如修改服务器上的数据)。GET请求常用于查询操作,例如搜索、排序和筛选等。
# POST请求:用于向服务器提交数据以创建新资源或更新现有资源,不是一个幂等的请求。POST请求可能会导致服务器上的状态改变,如创建新资源或更新现有资源。它常用于表单提交、文件上传和在服务器上执行某些操作
【3】小总结
-
django视图类于视图类的request-
request.POST只针对于post请求的urlencoded编码格式 才有数据 -
request.GET:请求地址栏中参数,无论什么方式,地址栏中都在这里-
但是它是这种方式:
<QueryDict: {'key': ['key', '99']}> -
取出方式
-
取出一个:
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-----文件部分
-
【二】新的Request对象和Response
【1】Request
-
以后我们写视图,全部用
cbv,cbv继承drf的APIView基类--》其实APIView继承了django的View -
继承
APIView后,响应统一用drf的响应-
request请求对象:
http请求的所有内容,都会在这个对象中 -
继承
APIView后的request对象和django的request的对象完全是两个不同的对象-
drf的request:rest_framework.request.Request -
django的request:django.core.handlers.wsgi.WSGIRequest
-
-
但是drf的request用起来的和原来的request是一样的
-
print(request.method) print(request.POST) print(request.GET) print(request.get_full_path())
-
-
request.data:
-
无论那种编码格式,请求体的数据,都在里面
-
urlencoded,form-data:是QueryDict的对象
-
json:是普通字典对象
-
单是都当字典用即可
-
-
但是由于编码格式的不同,可能是不同类的对象
-
-
reques.FILES:
-
前端传文件还是从这里面取
-
-
request.query_params:
-
查询?后面的参数
-
-
【2】Response
-
导入
from rest_framework.response import Response
-
使用
-
直接放字典,列表,字符串
-
是被放在了响应体中
-
-
-
放状态码
-
Response("ok",status=201)
-
-
如何放响应头:
-
Response("ok",status=201,headers={"xx":"xx})
-
-
总结:Response
-
data:响应体可以传字典,列表,字符串
-
status:http的响应状态码---》drf封装了所有常量--》HTTP_200_OK = 200
-
template_name :忽略----指定使用浏览器访问回来的模板,没有写的话,默认模板
-
headers:响应头
-
exception:异常
-
content_type:响应的编码格式,一般不用,大部分都用json
-
【三】序列化类的介绍
-
序列化类的作用:
-
前端传json格式的字符串给后端--》后端需要保存到数据库--》这个过程称之为反系列化
-
后端从数据库查出来的对象--》以json格式字符串传给前端--》这个过程称之为序列化
-
-
serializer就是为了完成上面的操作
-
完成序列化
-
反序列化
-
还有一个:反序列化校验
-
【四】序列化类的快速使用
【1】使用序列化类的使用步骤
-
首先创建一个序列化文件夹
serializer.py -
在里面创建创建一个序列化类,这个序列化类继承
Serializerfrom rest_framework import serializers # 定义序列化类,定义的序列化类要与,models里面定义的字段类都对应 class StudentSerializer(serializers.Serializer): # 定义的序列化字段的类型也要一样,里面不用写限制条件 name = serializers.CharField() age = serializers.IntegerField() gender = serializers.IntegerField()-
moderls.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, '女'), (3, '未知')))
-
-
在类中要写序列化的字段,这个序列化类里面的字段要与models里面的字段和字段类型一一对应
-
在视图类中使用
# 使用DRF种的Request返回序列化的数据
from rest_framework.response import Response
# 让视图类继承的父类
from rest_framework.views import APIView
# 导入模型表
from .models import Student
# 导入序列化类
from .serializer import StudentSerializer
# 在视图类中查询所有数据信息,用视图类继承APIView父类
class StudentView(APIView):
# 查询所有数据
def get(self, request):
data_all = Student.objects.all()
# print(data_all)
# 用你定义的序列化类,进行序列化
# instance:对应的是数序列化的数据
# many: 当它为True是代表序列化的实例不止一条
# 反之:当为False是序列化的实例只能是一条
# serializer对象:将包含序列化后的数据,但此时数据还没有被渲染成最终的响应体
serializer = StudentSerializer(instance=data_all, many=True)
# 我们用Response直接返回
# serializer.data: 通常会通过访问序列化器实例的.data属性来获取转换后的数据
# 因为.data属性包含了序列化后的数据,这些数据已经准备好以适当的格式(如JSON)返回给客户端
return Response(serializer.data)
# 在视图类中查询单个信息,用视图类继承APIView父类
class StudentDetailView(APIView):
def get(self, request, pk):
student_obj = Student.objects.filter(pk=pk).first()
# print(student_obj)
if not student_obj:
return HttpResponse("数据不存在!!")
serializer = StudentSerializer(instance=student_obj)
return Response(serializer.data)
-
这里有一个错误,你即使定义好了所有数据,配置好了所有的路径,什么东西都配置好了,但是你在浏览器访问还是会报下面这个错
-
是因为,我们用的序列化方法也相当于一个APP,所以需要在settings中注册
-
'rest_framework'
-
注册好后,你再访问你就可以看到数据了,而且还是好看的页面
-

【2】常用的字段类
-
记住一个中要的点:models中的字典的类型,一点要和序列化类里面的字段一一对
-
实在是记不住:你就把所有的字段类型设置成:CharField
| 字段 | 字段构造方式 |
|---|---|
| BooleanField | BooleanField() |
| NullBooleanField | NullBooleanField() |
| CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
| EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) |
| RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
| SlugField | SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+ |
| URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
| UUIDField | UUIDField(format=’hex_verbose’) format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a" |
| IPAddressField | IPAddressField(protocol=’both’, unpack_ipv4=False, **options) |
| IntegerField | IntegerField(max_value=None, min_value=None) |
| FloatField | FloatField(max_value=None, min_value=None) |
| DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 |
| DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
| DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
| TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
| DurationField | DurationField() |
| ChoiceField | ChoiceField(choices) choices与Django的用法相同 |
| MultipleChoiceField | MultipleChoiceField(choices) |
| FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
| ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
| ListField | ListField(child=, min_length=None, max_length=None) |
| DictField | DictField(child=) |
【3】常用的字段参数
-
序列化的字段类在实例化时传递参数的作用是
-
为了反序列化校验用
-
-
我们常用的有哪些字段参数
-
针对于
CharField-
max_length:最大长度
-
min_length:最小长度
-
allow_blank:是否允许为空
-
trim_whitespace 是否截断两头的空白字符
-
-
只针对于:IntegerField
-
max_value:最大值
-
min_value:最小值
-
-
只针对于:DateTimeField
-
format:序列化时,显示的格式
-
DateTimeField(format='Y-m-d')
-
-
-
所有字段类都用
-
required:是否必填
-
default:反序列化时使用的默认值
-
allow_null:表明该字段是否允许传入None,默认False
-
-
-
有两个重点后面会将
-
read_only:表明该字段仅用于序列化输出,默认False
-
write_only:表明该字段仅用于反序列化输入,默认False
-
【五】反序列化保存
【0】步骤
-
使用序列化类,继承
Serializer -
在字段类中写字段和字段参数,字段参数是当作校验用的
【1】新增数据
-
新增数据你需要在你的序列化类里面重写:create方法
from rest_framework import serializers
from app1.models import Student
# 定义序列化类,定义的序列化类要与,models里面定义的字段类都对应
class StudentSerializer(serializers.Serializer):
# 定义的序列化字段的类型也要一样,里面不用写限制条件
name = serializers.CharField()
age = serializers.IntegerField()
gender = serializers.IntegerField()
# 一定要重写create:不然不会报错
# 我们可一看到源码中的create什么都没干
def create(self, validated_data):
# validated_date:这个数据是前端传入,校验过后的数据
student = Student.objects.create(**validated_data)
# 一定要把新增的对象返回出去
# 因为我们调用serializer.data时,会使用序列化
return student
-
在视图类中加上校验规则,然后直接.create保存
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializer import StudentSerializer
# 在视图类中查询所有用视图类继承APIView父类
class StudentView(APIView):
def get(self, request):
# 这里就简写的get,主要看post
pass
def post(self, request):
# 添加数据
serializer = StudentSerializer(data=request.data)
# 反序列化校验,保存到数据库
if serializer.is_valid():
serializer.save()
# 序列化对象输出
# 而是将序列化后的数据作为HTTP响应返回给客户端
return Response(serializer.data)
else:
#
return Response({
"code": 101,
"msg": "数据校验失败!"
})
【2】修改数据
-
修改数据你需要在你的序列化类里面重写:update方法
from rest_framework import serializers
from app1.models import Student
# 定义序列化类,定义的序列化类要与,models里面定义的字段类都对应
class StudentSerializer(serializers.Serializer):
# 定义的序列化字段的类型也要一样,里面不用写限制条件
name = serializers.CharField()
age = serializers.IntegerField()
gender = serializers.IntegerField()
def update(self, instance, validated_data):
"""
:param instance: 等待修改的对象
:param validated_data: 前端传入校验后的数据
:return:
"""
# 第一种方法写
# instance.name = validated_data.get('name')
# instance.age = validated_data.get('age')
# instance.gender = validated_data.get('gender')
# 方式二
for key in validated_data:
# 这个是面向对象的反射方法,向当前对象中设置属性名和属性值
setattr(instance, key, validated_data[key])
instance.save()
return instance
-
视图类函数
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializer import StudentSerializer
from .models import Student
class StudentDetailView(APIView):
def put(self, request, pk):
# 对数据进行替换
student_obj = Student.objects.filter(pk=pk).first()
if not student_obj:
return Response({'code': 101, "mag": "数据不存在!"})
# instance对应老数据,data对应新数据,进行替换
serializer = StudentSerializer(instance=student_obj, data=request.data)
# 反序列化校验,保存到数据库
if serializer.is_valid():
# 保存
serializer.save()
return Response(serializer.data)
else:
return Response({
"code": 101,
"msg": "数据校验失败!"
})
【3】为什么要重写create和update方法
-
看源码
# 因为你用的seriarlizer.save,会触发self.create或self.update执行
# 我们没有写过,就要去父类里面找,父类里面没找到,找父类的父类,找到了
# 我们可以看到create方法和update方法什么也没做,我们没有重写这个方法的时候报的就是这个错
def create(self, validated_data):
raise NotImplementedError('`create()` must be implemented.')
def update(self, instance, validated_data):
raise NotImplementedError('`update()` must be implemented.')
-
现在问题来了
-
我们明明调用的都是save,为什么会执行create和update方法呢
-
而且我们也没有写save这个方法,就要去父类里面找,父类里面没找到,找父类的父类,找到了
-
看源码
-
# 这个self是我们自己序列化类的对象
# 我们一看到,如果是修改的时候instance是不能等于None的
if self.instance is not None:
# 这里=self.update()我们自己重写了,调用的我们自己的
self.instance = self.update(self.instance, validated_data)
else:
# 如果self.instance没值,他就是添加数据
self.instance = self.create(validated_data)
return self.instance

被折叠的 条评论
为什么被折叠?



