1 cbv执行流程
-路由里写的是 类名.as_view(),
-as_view()执行完是一个闭包函数的内存地址
-当请求来了,路由匹配上就会调用 闭包函数(request)
-self.dispatch(requset)
-通过反射,去类中根据请求方式取方法,执行,把参数传入
2 APIView的执行流程
-以后写drf,最顶层都是APIView
-类名.as_view()是APIView,内部调用了父类的view
-在后加了去除csrf
-self.dispatch(requset)是APIView的
-包装新的request
-执行了权限,频率,认证
-处理了全局异常
-处理了响应
4 drf的Request类
-重写了__getattr__ :新的request用起来,跟之前一模一样
-drf的reqeust._request 是原来的request
-request.data :post,put,patch,请求的body体中的数据,都从data中取
5 序列化,反序列化
-对象----》json
-json---》对象
6 序列化器
-定义一个类,继承Serializer
-在类内些字段(常用字段,和非常用字段)(字段参数)
-在视图类中,实例化得到一个序列化类的对象,传入要序列化的数据
-对象.data---》就是字典
-source
1 反序列化,局部钩子,全局钩子
1 如果要反序列化,继承了Serializer,必须重写create方法
2 使用
#视图类
def post(self, request):
publish_ser = serializer.PublishSerializer(data=request.data)
if publish_ser.is_valid():
# 直接保存,保存到哪个表里?需要重写save
publish_ser.save()
return Response(publish_ser.data)
else:
print(publish_ser.errors)
return Response('数据有问题啊')
# 序列化类
def create(self, validated_data):
res = models.Publish.objects.create(**validated_data)
return res
1.3 局部和全局钩子
def validate_name(self, data):
# data就是当前字段的值
if data.startswith('sb'):
raise ValidationError('不能以sb开头')
else:
return data
def validate(self, attrs):
if attrs.get('name') == attrs.get('city'):
raise ValidationError('city和名字不能一样')
else:
return attrs
2 序列化类常用字段属性
2.1 常用和非常用字段
http://www.liuqingzheng.top/python/Django-rest-framework%E6%A1%86%E6%9E%B6/2-drf-%E5%BA%8F%E5%88%97%E5%8C%96%E7%BB%84%E4%BB%B6/
2.2 字段参数
# 针对charfield
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
# 针对interfield
max_value 最小值
min_value 最大值
# 通用的,大家都有
#这两个最重要
read_only 表明该字段仅用于序列化输出,默认False(序列化)
write_only 表明该字段仅用于反序列化输入,默认False(反序列化)
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
error_messages 包含错误编号与错误信息的字典
validators 该字段使用的验证器(了解)
3 模型序列化器
2.1 视图类
class BookView(APIView):
def get(self,request):
qs=models.Book.objects.all()
ser=serializer.BookModelSerializer(instance=qs,many=True)
return Response(ser.data)
def post(self,request):
ser = serializer.BookModelSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
class BookDetailView(APIView):
def get(self,request,id):
book = models.Book.objects.filter(pk=id).first()
ser = serializer.BookModelSerializer(instance=book)
return Response(ser.data)
def put(self,request,id):
book = models.Book.objects.filter(pk=id).first()
ser = serializer.BookModelSerializer(instance=book,data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
def delete(self,request,id):
res = models.Book.objects.filter(pk=id).delete()
if res[0] > 0:
return Response('')
else:
return Response('要删的不存在')
3.2 序列化类
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = '__all__'
extra_kwargs = {
'publish': {'required': True, 'write_only': True},
'authors': {'required': True, 'write_only': True},
}
publish_detail = PublishSerializer(source='publish',read_only=True)
author_list=serializers.ListField(read_only=True)
# 字段自己的校验,全局钩子,局部钩子
3.3 表模型
class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish_date = models.DateField()
publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
authors=models.ManyToManyField(to='Author')
def __str__(self):
return self.name
# def publish_name(self):
# return self.publish.name
def publish_name(self):
return {'name':self.publish.name,'city':self.publish.city}
3.4 路由
path('books/',views.BookView.as_view()),
path('books/<int:id>/',views.BookDetailView.as_view()),
4 请求对象
1 Request:新的request
2 常用属性
1).data
request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST和 request.FILES属性,但提供如下特性:
包含了解析之后的文件和非文件数据
包含了对POST、PUT、PATCH请求方式解析后的数据
利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
2).query_params
request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已
5 响应对象属性
#一直会用
data: 为响应准备的序列化处理后的数据(字典)
#偶尔会用
headers: 用于存放响应头信息的字典;
status: 状态码,默认200;(http请求的状态码)
# 基本不用
template_name: 模板名称,如果使用HTMLRenderer 时需指明;
content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
补充
1 django项目,app中有templates,找模板优先从项目的templates中找,找不到,去相应的app中找,找不到,再报错