drf快速入门02---ModelSerializer的使用&many=True源码分析

一. 基于ModelSerializer的增删查改

model

from django.db import models


# Create your models here.


class Book(models.Model):
    name = models.CharField(verbose_name='书名', max_length=32)
    price = models.DecimalField(verbose_name='价格', decimal_places=2, max_digits=5)
    publish = models.ForeignKey(verbose_name='出版社', to='Publish', on_delete=models.DO_NOTHING)


class Publish(models.Model):
    name = models.CharField(verbose_name='名称', max_length=32)

url

from django.urls import path, re_path
from app01 import views

urlpatterns = [
    path('text_2/', views.Text3View.as_view()),
    re_path(r'^text_2/(?P<pk>\d+)/$', views.Text4View.as_view()),
]

view

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

from . import models
from .sealizer import TextModelSerializer


class Text3View(APIView):
    def get(self, request):
        # 群查
        # 1. 获取表模型对象
        book_queryset = models.Book.objects.all()
        # 2. 示例化序列化器对象 固定格式如果是序列化多条一定要填一个many=True
        text_book = TextModelSerializer(instance=book_queryset, many=True)
        book_data = {
            "status": 200,
            "msg": "ok",
            "data": text_book.data,
        }
        return Response(data=book_data, status=status.HTTP_200_OK)

    def post(self, request):
        # 新增  request.data--除了GET请求的参数,其他的请求携带数据,都是从request.data这里拿
        text_book = TextModelSerializer(data=request.data)
        book_data = {
            "status": 200,
            "msg": "ok",
            "data": "",
        }
        if text_book.is_valid():
            # 注意如果是serializer的话,必须重写create,不然报错
            text_book.save()
            book_data['data'] = text_book.data
            return Response(data=book_data, status=status.HTTP_200_OK)
        book_data['status'] = 400
        book_data['msg'] = text_book.errors
        return Response(data=book_data, status=status.HTTP_400_BAD_REQUEST)


class Text4View(APIView):
    def get(self, request, pk):
        # 单查
        # 1. 获取表模型对象
        book_obj = models.Book.objects.get(pk=pk)
        # 2. 示例化序列化器对象 固定格式
        text_book = TextModelSerializer(instance=book_obj)
        book_data = {
            "status": 200,
            "msg": "ok",
            "data": text_book.data,
        }
        return Response(data=book_data, status=status.HTTP_200_OK)

    def patch(self, request, pk):
        # 局部修改  request.data--除了GET请求的参数,其他的请求携带数据,都是从request.data这里拿
        old_book_obj = models.Book.objects.get(pk=pk)
        text_book = TextModelSerializer(instance=old_book_obj, data=request.data)
        book_data = {
            "status": 200,
            "msg": "ok",
            "data": "",
        }
        if text_book.is_valid():
            # 注意如果是serializer的话,必须重写update,不然报错
            text_book.save()
            book_data['data'] = text_book.data
            return Response(data=book_data, status=status.HTTP_200_OK)
        book_data['status'] = 400
        book_data['msg'] = text_book.errors
        return Response(data=book_data, status=status.HTTP_400_BAD_REQUEST)

    def put(self, request, pk):
        # 全局修改  request.data--除了GET请求的参数,其他的请求携带数据,都是从request.data这里拿
        old_book_obj = models.Book.objects.get(pk=pk)
        text_book = TextModelSerializer(instance=old_book_obj, data=request.data)
        book_data = {
            "status": 200,
            "msg": "ok",
            "data": "",
        }
        if text_book.is_valid():
            # 注意如果是serializer的话,必须重写update,不然报错
            text_book.save()
            book_data['data'] = text_book.data
            return Response(data=book_data, status=status.HTTP_200_OK)
        book_data['status'] = 400
        book_data['msg'] = text_book.errors
        return Response(data=book_data, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        book_data = {
            "status": 200,
            "msg": "ok",
            "data": "",
        }
        models.Book.objects.get(pk=pk).delete()
        return Response(data=book_data, status=status.HTTP_200_OK)

ModelSerializer

from rest_framework import serializers

from .views import models


class TextModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book  # 对应上models.py中的模型
        # fields = '__all__' # 全部字段显示
        fields = ['id', 'name', 'price', 'publish']  # 只序列化指定的字段
        # exclude=('name',) #跟fields不能都写,写谁,就表示排除谁 ,只能单独使用

        extra_kwargs = {
            'id': {'read_only': True},  # 只校验序列化,反序列化不校验
            'name': {'write_only': True},  # 只校验反序列化,不校验序列化
        }

二 write_only/read_only的作用

write/read_only详解https://blog.csdn.net/qq_52385631/article/details/122767023?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164502182416780274164243%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=164502182416780274164243&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-122767023.nonecase&utm_term=write&spm=1018.2226.3001.4450

三. ModelSerializer的高级用法

自定义字段返回类型&序列化器嵌套https://blog.csdn.net/qq_52385631/article/details/122767023?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164502182416780274164243%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=164502182416780274164243&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-122767023.nonecase&utm_term=write&spm=1018.2226.3001.4450

四. many=True源码分析

a. 传many=True,跟不传many=True,实例化的序列化器对象都不一样

b. 通过__new__控制的

# 序列化多条,需要传many=True
book_ser=BookModelSerializer(books,many=True)
book_one_ser=BookModelSerializer(book)
print(type(book_ser))
#<class 'rest_framework.serializers.ListSerializer'>
print(type(book_one_ser))
#<class 'app01.ser.BookModelSerializer'>

# 对象的生成--》先调用类的__new__方法,生成空对象
# 对象=类名(name=lqz),触发类的__init__()
# 类的__new__方法控制对象的生成


def __new__(cls, *args, **kwargs):
    if kwargs.pop('many', False):
        return cls.many_init(*args, **kwargs)
    # 没有传many=True,走下面,正常的对象实例化
    return super().__new__(cls, *args, **kwargs)

五. context 参数

a. 作用:

视图与序列化器参数互传,很多人都传request,实际上视图跟序列化器上,都封装了request

b. 视图中封装的request,

(在GenericAPIView---get_serializer---get_serializer_context)

    def get_serializer(self, *args, **kwargs):
        
        serializer_class = self.get_serializer_class()
        kwargs.setdefault('context', self.get_serializer_context())
        return serializer_class(*args, **kwargs)

     def get_serializer_context(self):
        
        return {
            'request': self.request,
            'format': self.format_kwarg,
            'view': self
        }

序列化器取request &视图取request

# 序列化器
request = self.context['request']
# 视图
request = self.request

 c. 视图甚至可以重写GenericAPIView的get_queryset来获取request

def get_queryset(self):
        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            queryset = queryset.all()
        return queryset

重写示例

class OrderDataView(ListAPIView):
    """查询属于与自己的订单"""
    permission_classes = [IsAuthenticated, ]
    serializer_class = OrderDataModelSerializer

    def get_queryset(self):
        queryset = models.Order.objects.filter(user=self.request.user, is_deleted=False)

        return queryset

d. 视图放/取值《---》序列化放取值

视图放
serializer = XXXSerializer(XXX, context={'id': id})
序列化器取
request = self.context.get('id')

序列化器放
self.context['id'] = user.id
视图取
serializer_obj.context.get('id'),




user_dic = {
                'id': serializer_obj.context.get('id'),
                'username': serializer_obj.context.get('username'),
                'token': serializer_obj.context.get('token'),
            }

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑猪去兜风z1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值