一、RESTful规范
1.1 REST风格:表属性状态转移
1.1.1资源:在web中凡是有被引用的必要的都叫资源
1.1.2 URI:统一资源标识符 URI包含URL
1.1.3 URL:统一资源定位符
1.1.4 统一资源接口,不再像以前django项目中url中增删改查都分别对应一个url,而是url中只写一个名词最为代表性的
路由,比如(只写book,不需要book_list,book_append,book_edit,book_delate),其他的功能根据HTTP请求方式
的不同来对资源进行操作。
1.1.5 前后端传递的是资源的表述
1.1.6 前端展示的是资源的状态
1.1.7 通过超链接的指引来告诉用户接下来有哪些资源状态可以进入
1.2 核心思想:
1.2.1 面向对象去编程,url中尽量用名词,不要用动词
1.2.2 根据HTTP请求方式的不同对资源进行不同的操作。
1.3 url中要体现的信息
1.3.1 版本
1.3.2 API
1.3.3 过滤条件
1.3.4 HTTPS
1.4 返回的要求
1.4.1 要携带状态吗
1.4.2 返回值
1 get 获取的是所有或者单挑数据 2 3 post 返回的是新增的这条数据 4 5 put/patch 返回的是更新的数据 6 7 delete 返回空
1.4.3 携带错误信息
1.4.4 携带超链接
二、FBV 和 CBV 的区别
1 def dispatch(self, request, *args, **kwargs): 2 # GET POST 3 # BookView().get 4 # DJango的View只做了CBV的分发 5 if request.method.lower() in self.http_method_names: 6 handler = getattr(self, request.method.lower(), self.http_method_not_allowed) 7 else: 8 handler = self.http_method_not_allowed 9 return handler(request, *args, **kwargs)
三、下载DRF
1 pip istall djangorestframwork -i https://pypi.tuna.tsinghua.edu.cn/simple
在settings的APP项中注册rest_framwork
四、APIView 和View的区别
4.1、APIView继承了View
4.2、重写了as_view方法,豁免了csrf
4.3、重新封装了request
1 新的request变成了Request的实例化对象, 2 3 request = self.initialize_request(request, *args, **kwargs) 4 self.request = request 5 6 旧的request 变成了_request 7 8 self._request = 旧的request 9 10 def query_params(self): 11 return self._request.GET 12 def data(self): 13 return post请求的数据
五、序列化
5.1 django实现序列化
5.1.1 通过.values 获取到QuerySet对象 ,通过JsonResponse进行序列化。JsonResponse和HttpResponse的区别是能
够处理date/datetime类型的数据,但都不能解决外键关系的序列化
5.1.2 django的序列化器 serializes.seialize 能够序列化queryset,但是也不能解决外间关系的序列化
5.2 DRF的序列化组件
5.2.1 先声明一个序列化器,类比django中的model.py文件
5.2.2 在视图中使用序列化器序列化queryset
5.2.3 序列化好的数据在set_obj.data中
5.3 对于GET请求
5.3.1 先获取Book对象的所有信息
book_queryset = Book.objects.all()
5.3.2 ser_obj = BookSerializer(book_queryset,many=True)
如果有many=True 认为我们的queryset是一个可迭代对象,循环我们的queryset拿到每一个模型对象
把每个模型对象的字段跟序列化器的字段进行匹配,匹配成功的进行序列化,没有匹配成功的丢弃,
但是序列化器里的字段必须在要匹配的字段中
5.4 对于POST请求
5.4.1 注意序列化和反序列化不统一的字段
id = serializers.IntegerField(required=False) required=False表示之序列化,不进行校验
read_only = True :表示只进行正向序列化
write_only = True:表示只进行反向序列化
5.4.2 视图中
1 def post(self, request): 2 book_obj = request.data # data是post提交的数据 3 ser_obj = BookSerializer(data=book_obj) 4 print(type(ser_obj), ser_obj) 5 if ser_obj.is_valid(): 6 ser_obj.save() # 此save不同于ORM操作中的save,此save只是单纯的调用了create方法,所以要去重写create方法,其实是create方法对数据进行了保存 7 return Response(ser_obj.validated_data) 8 return Response(ser_obj.errors)
5.4.3 重写create方法
1 def create(self, validated_data): 2 book_obj = Book.objects.create(title=validated_data['title'], 3 publisher_time=validated_data['publisher_time'], 4 category=validated_data['post_category'], 5 publisher_id=validated_data['publisher_id'], 6 ) 7 book_obj.authors.add(*validated_data['author_list']) 8 return book_obj
5.5对于PUT/PATCH请求
5.5.1在视图中
1 def put(self, request, id): 2 book_obj = Book.objects.filter(id=id).first() 3 ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True) 4 if ser_obj.is_valid(): 5 ser_obj.save() # 在put中,save()的时候需要重写update方法 6 return Response(ser_obj.validated_data) 7 return Response(ser_obj.errors)
5.5.2重写的update
1 def update(self, instance, validated_data): 2 # instance 更新的book_obj 对象 3 # validated_data 校验通过的数据 4 # ORM做更新操作 5 instance.title = validated_data.get("title", instance.title) #字典.get取值的时候即使没有也不会报错 6 instance.pub_time = validated_data.get("pub_time", instance.pub_time) 7 instance.category = validated_data.get("post_category", instance.category) 8 instance.publisher_id = validated_data.get("publisher_id", instance.publisher_id) 9 if validated_data.get("author_list"): 10 instance.authors.set(validated_data["author_list"]) 11 instance.save() 12 return instance
6.1验证
6.1.1局部钩子函数
1 def validate_title(self, value): # 局部钩子需要传value作为参数 2 print(2222) 3 # value就是title的值 对value处理 4 if "python" not in value.lower(): 5 raise serializers.ValidationError("标题必须含有python") 6 return value
6.1.2全局钩子函数
1 def validate(self, attrs): # 全局钩子,需要传参数attrs 2 print(33333) 3 # attrs 字典有你传过来的所有的字段 4 print(attrs) 5 if "python" in attrs["title"].lower() or attrs["post_category"] == 1: 6 return attrs 7 else: 8 raise serializers.ValidationError("分类或标题不合符要求")
6.1.3自定义验证函数
1 def my_validate(value): # 自定义的函数,没有self,把value作为参数 2 print(1111) 3 if "敏感信息" in value.lower(): 4 raise serializers.ValidationError("有敏感词汇") 5 return value 6 # 对于自定义的函数,需要在序列化器中的字段中加入validators=[my_validate,] 7 # title = serializers.CharField(max_length=32, validators=[my_validate,])
6.1.4 验证的钩子函数,优先级分别是 自定义 > 局部钩子 > 全局钩子
6.1.5 普通序列化器处理正反序列化的方法
1 from rest_framework import serializers 2 from DRF_Demo.models import Book, Publisher 3 from rest_framework.response import Response 4 5 6 class PublisherSerializer(serializers.Serializer): 7 id = serializers.IntegerField() 8 name = serializers.CharField(max_length=32) 9 10 11 class AuthorSerializer(serializers.Serializer): 12 id = serializers.IntegerField() 13 name = serializers.CharField(max_length=32) 14 15 16 class BookSerializer(serializers.Serializer): 17 id = serializers.IntegerField(required=False) # required=False 只序列化不校验 18 title = serializers.CharField(max_length=32) 19 publisher_time = serializers.DateField() 20 category = serializers.CharField(source='get_category_display', read_only=True) 21 22 publisher = PublisherSerializer(read_only=True) 23 authors = AuthorSerializer(many=True, read_only=True) 24 post_category = serializers.IntegerField(write_only=True) # 对于反序列化的字段名称匹配的时候,要和提交的数据的字段相同 25 publisher_id = serializers.IntegerField(write_only=True) 26 author_list = serializers.ListField(write_only=True) 27 28 def create(self, validated_data): 29 book_obj = Book.objects.create(title=validated_data['title'], 30 publisher_time=validated_data['publisher_time'], 31 category=validated_data['post_category'], 32 publisher_id=validated_data['publisher_id'], 33 ) 34 book_obj.authors.add(*validated_data['author_list']) 35 return book_obj 36 37 def update(self, instance, validated_data): 38 instance.title = validated_data.get("title", instance.title) 39 instance.save() 40 return instance
7.1 ModelSerializer
7.1.1 类似于Django中的modelform,用于生成关联的模型里的所有字段
model=表名
fields="__all__"/["字段名",]
exclude=["字段名",]
depth=1 外键关系找一层 会让外键关系字段变成read_only=True
extra_kwargs={"字段名": {配置的属性}} # 对于不想要正序或者反序的字段,就用extra_kwargs={'字段名':属性}}
7.1.2 SerlizerMethodField() 对于重写的正向序列化的字段,用这个方法字段来定义
7.1.2 示例,用ModelSerilizer方法进行正反序列化,包括校验字段
1 class BookSerializer(serializers.ModelSerializer): 2 # SerializerMethodField是个方法字段,需要用get_publisher_info 来定义方法 3 publisher_info = serializers.SerializerMethodField(read_only=True) 4 authors_info = serializers.SerializerMethodField(read_only=True) 5 6 # 通过get_变量名制定方法,obj是Book对象 7 def get_publisher_info(self, obj): 8 publisher_obj = obj.publisher 9 # return 回来的结果返回给publisher_info,然后渲染到页面上 10 return {"id": publisher_obj.id, "name": publisher_obj.name} 11 12 def get_authors_info(self, obj): 13 authors_obj = obj.authors.all() 14 return [{'id': author.id, 'name': author.name} for author in authors_obj] 15 16 class Meta: 17 model = Book 18 fields = '__all__' 19 # depth = 1 # depth 写几就是外键向下找几层,一般不要超过四层。并且会让所有外键变成read_only=True 20 # extra_kwargs 是一个字典,处理序列化的字段,如果正向序列化不想要展现publisher 和authors字段,就将他设置成write_only=True 21 extra_kwargs = {'publisher': {"write_only": True}, 'authors': {"write_only": True}} 22 # 定义一个局部钩子函数,validate_字段名,校验title,参数要传一个value 23 def validate_title(self, value): 24 if 'python' not in value.lower(): 25 raise serializers.ValidationError('标题必须含有python') 26 return value 27 def validate(self,attrs): 28 if 'python' in attrs["title"].lower() or attrs["authors_info.id"] == 1: 29 return attrs 30 else: 31 raise serializers.ValidationError('分类或标题不符合要求')