【三】DRF序列化进阶

【 一 】request对象

request是被drf封装了一层新的request对象,django原生的request 封装在新对象的_request属性里,可以使用request._request访问原生requestdjango为了方便 封装时通过__getattribute____getattr__做了处理 直接使用request.method也能访问到request._request.method

1.解析器

不用的话 默认支持JSONParser,FormParser,MultiPartParser三种解析器

需要改默认 需要改全局配置 setting里新增

例:DEFAULT_PARSER_CLASSES":[“rest_framework.parsers.JSONParser”]

单个配置解析器JSONParser,FormParser
from rest_framework.parsers import JSONParser, FormParser
from rest_framework.negotiation import DefaultContentNegotiation

class UserInFo(APIView):
    def get(self,request, *args,**kwargs):
        # 所有解析器
        parser_classes = [JSONParser,FormParser] #JSON格式和formdata
        # 根据请求,匹配对应的解析器  寻找
        content_negotiation_class = DefaultContentNegotiation

        #获取参数方法
    	request.query_params.get("id") #获取get url参数 id

        #post请求
		#request.data
       
文件解析器
from rest_framework.parsers import MultiPartParser
class UserInFo(APIView):
    def post(self,request,params):
        parser_classes = [ MultiPartParser] #文件解析器包括 文件和其他表单
        #获取文件对象
    	file=request.data.get("img")
    	

2.获取参数

1.读取请求头的content-type类型读取

2.根据不同类型获取解析器

#http://127.0.0.1:8000/getUserInfo/?id=1&&name=xxxx
request.query_params.get("id") #获取get url参数 id

request.data #获取请求体 post 参数

【 二 】DRF 中的模型序列化(重要)

image-20240413151737446

【0】为什么要使用序列化

'''1 基于APIView写5个接口
	-做序列化的时候,方法很笨,手动做的
    -后期如果想多序列化某个或少序列化某个字段,比较麻烦
    '''
    
#2 借助于 drf 提供的序列化类
	1 帮助我们快速序列化
    2 帮助我们做反序列化之前的数据校验
    3 帮助我们做反序列化
    
# 3 序列化类使用之序列化
	3.1 写一个类,继承Serialier
    3.2 在类中写字段,字段就是要序列化的字段
    3.3 在视图函数中,序列化类,实例化得到对象,传入该传的参数
    	- 多条
        - 单条
    3.4 调用序列化类对象的 serializer.data 方法完成序列化

【1】序列化组件使用原理

  1. 序列化: 序列化器会把模型对象转换成字典,经过response以后变成json字符串
  2. 反序列化: 把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
  3. 反序列化: 完成数据校验功能

【2】序列化组件serializer的简单使用

写一个序列化类

在类中写要序列化的字段,想序列化哪个字段,就在类中写哪个字段

在视图类中导入该序列化类,实例化序列化类得到序列化类的对象,将需要序列化的对象传入

序列化类的对象.data 是一个字典

把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse

【3】序列化之查询、删除指定id的接口

# 1 基于View+JsonResponse编写5个接口
	-1 序列化需要自己做
    -2 post提交数据,如果是json格式,在request.POST取不到数据--》request.body
    	dic=json.loads(request.body) # request.body  bytes格式
        Book.objects.create(**dic)
  • 创建任意名称的py文件,在该文件中创建序列化类,该序列化类需要继承APIView from。
问:

这个序列化创建的表跟我models.py文件中的Book的表并是不是同一张表

答:

在 Django 中,models.py中定义的模型类和rest_framework 中的序列化器不是同一个概念。

在使用 Django REST Framework 进行 API 开发时,通常需要同时使用模型类和序列化器

  1. 模型类(Model):模型类定义了数据的结构,它们对应于数据库中的表。通过定义模型类,您可以轻松地与数据库进行交互,包括检索、创建、更新和删除数据。
  2. 序列化器(Serializer):序列化器用于定义 API 的输入和输出格式。它们负责将模型类实例转换为 JSON 或其他格式,以便通过 API 进行传输,并且还能够将传入的数据反序列化为模型实例。序列化器还可以用于验证传入的数据是否符合预期的格式和规则。

​ 通过使用序列化器,您可以轻松地在 Django 中创建强大的 RESTful API,而无需手动编写数据转换和验证逻辑。序列化器可以帮助您更高效地处理数据,并提供了一种清晰的方式来定义 API 的输入和输出格式。

【3.0】JsonResponse跟Response的区别

JsonResponseResponse 是用于在 Django 中返回 HTTP 响应的两种不同方式。

  1. JsonResponse

    • JsonResponse 是 Django 中的一个类,用于返回 JSON 数据格式的 HTTP 响应。
    • 它是从 django.http 模块中导入的,通常用于 Django 视图函数中。
    • 使用 JsonResponse 可以方便地将 Python 数据结构(如字典或列表)转换为 JSON 格式,并将其作为响应的主体返回给客户端。

示例:

from django.http import JsonResponse

def my_view(request):
    data = {'key': 'value'}
    return JsonResponse(data)
  1. Response

    • Response 是 Django REST Framework(DRF)中的一个类,用于返回 HTTP 响应。
    • 它是从 rest_framework.response 模块中导入的,用于 DRF 的视图函数或视图类中。
    • Response 不仅可以返回 JSON 格式的数据,还可以返回其他格式的数据(如 XML、HTML 等)。
    • 它提供了更多的灵活性和功能,如内容协商(Content Negotiation)、状态码的自定义、序列化器的使用等。

示例:

from rest_framework.response import Response
from rest_framework.views import APIView

class MyAPIView(APIView):
    def get(self, request):
        data = {'key': 'value'}
        return Response(data)

​ 总的来说,JsonResponse 适用于基于 Django 的项目,特别是在处理简单的 JSON 数据时;而 Response 适用于使用 Django REST Framework 构建的 API,提供了更多的功能和灵活性。

【3.1】定义一个Serializer序列化器

from django.db import models


class Book(models.Model):
    name = models.CharField(max_length=88)
    price = models.IntegerField()
    publish = models.CharField(max_length=66)
问:

是不是在views.py中使用-序列化后就不需要用from django.http import JsonResponse这个的方法来而是用from rest_framework.response import Response这个方法对吧

答:

​ 在 Django REST Framework 中,通常使用 Response 类来返回 API 的响应,而不是直接使用 Django 中的 JsonResponseResponse 类提供了更多的功能,可以自动将数据序列化为 JSON(或其他格式),并设置正确的 HTTP 头部。这使得处理 API 响应更加简单和灵活。

【3.2】在views.py

  • 在序列化数据的时候,需要指定many=True,因为查到的数据是多条
  • 不需要定义serializer.py文件
def get(self, request):
    books = Book.objects.all()
    book_ser = BookSerializer(books, many=True)
    return Response(book_ser.data)
from .models import Book
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer

# 查询多条数据
# http://127.0.0.1:8000/Api01/books/
class BookView(APIView):
    def get(self, request):
        res_list = Book.objects.all()
        # 要序列化的qs对象,但是如果是多条数据,必须加 many=True
        serializer = BookSerializer(instance=res_list, many=True)  # instance=None, data=empty
        return Response({'code': 100, 'msg': '查询成功', 'results': serializer.data})
  
# 查询单条数据
# http://127.0.0.1:8000/Api01/books/1/
class BookDetailView(APIView):
    def get(self, request,pk):
        res_list = Book.objects.filter(pk=pk).first()
        # 要序列化的qs对象,但是如果是多条数据,必须加 many=True 则单条不用
        serializer = BookSerializer(res_list)
        return Response({'code': 100, 'msg': '查询成功', 'results': serializer.data})

image-20240412215058507

image-20240412215709344

  • 删除跟查询一样
from .models import Book
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
from rest_framework import status
from django.shortcuts import get_object_or_404
class BookView(APIView):
    def delete(self,request,pk):
        # try:
        #     # 尝试获取要删除的书籍对象
        #     book = Book.objects.get(pk=pk)
        # except Book.DoesNotExist:
        #     # 如果找不到对应的书籍,则返回 404 错误
        #     raise NotFound("Book not found")

        instace = get_object_or_404(Book,pk=pk)
        instace.delete()
        return  Response({'code': 100, 'msg': '查询成功'}, status=status.HTTP_204_NO_CONTENT)
    
    

image-20240412232908223

注意:

​ 我在上述的代码中,BookView 类继承自 Django Rest Framework 的 APIView 类,用于处理书籍的查询请求。在 get 方法中,您使用 Book.objects.all() 查询了所有的书籍记录,并将其序列化为 JSON 格式的数据,然后将其作为响应返回给客户端。

​ 对于添加、更新和删除操作,您需要更复杂的逻辑来确保数据的合法性和完整性。一般来说,这些操作需要在视图中进行验证,并根据验证结果执行相应的操作。在 Django Rest Framework 中,您可以通过重写视图的 postputpatchdelete 方法来实现这些操作。

【4】反序列化之更改、增加数据

  • 增、改

  • 这个就用到了from rest_framework.exceptions import ValidationError跟函数的validated_data的方法了。

  • 在我们定义的Serializers.py文件中

  • 需要在序列化类中定义校验规则,如果客户端返回给后端的数据符合校验规则,就需要将数据保存到数据库,当数据通过校验的时候,如果不在序列化类中重写update方法就会抛出异常。

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from Api01.models import Book

class BookSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.IntegerField()
    publish = serializers.CharField()


    def create(self,validated_data):
        # 简单的来说就是验证book里面的数据是否合法
        book = Book.objects.create(**validated_data)
        return book
    
    def update(self, instance, validated_data):
        # instance:对象
        # validated_data 数据
        # 笨办法-y优化--》使用反射
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.publish = validated_data.get('publish')
        instance.save()  # 更改保存到数据中
        return instance
  • urls.py
from django.urls import path,include
# BookView、BookDetailView 这个就是我在views.py 定义的类
from Api01.views import BookView,BookDetailView  
urlpatterns = [
    path('books/', BookView.as_view()),
    path('books/<int:pk>/', BookView.as_view()),

]
  • views.py

class BookView(APIView):
    def post(self, request):
        # 前端无论以什么编码格式--》提交到后端你的数据,都会被解析到 request.data 中,是个字典
        # 如果是urlencoded或form-data编码--》不能直接这样写,要写成如下
        # 提取请求数据
        data = request.data
        print(data)
        # <QueryDict: {'name': ['啊啥的'], 'price': ['222'], 'publish': ['啊啥的']}>
        # 使用序列化器验证数据
        obj = BookSerializer(data=data)
        print(obj)
        if obj.is_valid():
            # 如果数据有效,创建新的书籍对象
            obj.save()
            return Response({'code': 200,'mes':'添加成功'})
        else:
            return Response({'code': 200,'mes':'添加失败!!!','errors':obj.errors})
        
        
  • 同理在BookDetailView也是一样的代码

class BookDetailView(APIView):
    def post(self, request):
        # 前端无论以什么编码格式--》提交到后端你的数据,都会被解析到 request.data 中,是个字典
        # 如果是urlencoded或form-data编码--》不能直接这样写,要写成如下
        # 提取请求数据
        data = request.data
        print(data)
        # 使用序列化器验证数据
        obj = BookSerializer(data=data)
        print(obj)
        if obj.is_valid():
            # 如果数据有效,创建新的书籍对象
            obj.save()
            return Response({'code': 200,'mes':'添加成功'})
        else:
            return Response({'code': 200,'mes':'添加失败!!!','errors':obj.errors})
        
        

image-20240412225806651

class BookDetailView(APIView):
    def put(self,request,pk):
        # 提取请求数据
        data = request.data
        print(data)
        book = Book.objects.filter(pk=pk).first()
        res_data = BookSerializer(instance=book, data=data)
        # 如果数据有效,保存更新后的书籍对象
        # serializer.is_valid()
        print(res_data)
        if res_data.is_valid():
            res_data.save()
            return Response({'code': 100, 'msg': '更改成功!!!'})
        else:
            return Response({'code': 200, 'mes': '找不到表中的数据', 'errors': res_data.errors})

image-20240413000123667

image-20240413000140546

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值