3

DRF Serializer 的many参数是干嘛的

 2 years ago
source link: https://segmentfault.com/a/1190000039945793
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

DRF Serializer 的many参数是干嘛的

发布于 今天 08:05

Django rest framework

什么时候需要用many参数呢?

  • 当构造序列化的时候,传递的参数的QuerySet实例,就需要用many=True参数,即便QuerySet长度为0或者长度为1
  • 当构造序列化的时候,传递的参数的某个模型实例(内置的User实例,或者自定义的模型实例),就需要用many=false参数
class BaseSerializer(Field):
    def __init__(self, instance=None, data=empty, **kwargs):
        self.instance = instance
        if data is not empty:
            self.initial_data = data
        self.partial = kwargs.pop('partial', False)
        self._context = kwargs.pop('context', {})
        kwargs.pop('many', None)
        super().__init__(**kwargs)
        
    def __new__(cls, *args, **kwargs):
        if kwargs.pop('many', False):
            return cls.many_init(*args, **kwargs)
        return super().__new__(cls, *args, **kwargs)

    @classmethod
    def many_init(cls, *args, **kwargs):

        allow_empty = kwargs.pop('allow_empty', None)
        child_serializer = cls(*args, **kwargs)
        list_kwargs = {
            'child': child_serializer,
        }
        if allow_empty is not None:
            list_kwargs['allow_empty'] = allow_empty
        list_kwargs.update({
            key: value for key, value in kwargs.items()
            if key in LIST_SERIALIZER_KWARGS
        })
        meta = getattr(cls, 'Meta', None)
        list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
        return list_serializer_class(*args, **list_kwargs)

当使用如下的语句进行序列化操作的时候。
serializer = TweetSerializer(queryset, many=True)
queryset会被赋值给BaseSerializer对应的构造方法def __init__(self, instance=None, data=empty, **kwargs):中的instance参数。
当instance参数接受的是QuerySet实例,就需要加many=True,如果instance接受的某个模型实例,例如TweetModel

class TweetAPIView(mixins.ListModelMixin,
                   mixins.CreateModelMixin,
                   GenericAPIView
                   ):
    queryset = TweetModel.objects.all()
    serializer_class = TweetCreateSerializer

    def get(self, request: Request):
        return self.list(request)

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        serializer = TweetSerializer(queryset, many=True)
        return Response(serializer.data)

    def post(self, request: Request):
        return self.create(request)
class TweetModel(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    title = models.CharField(max_length=32, verbose_name='标题')
    content = models.TextField(verbose_name='正文')

    photos = models.ManyToManyField(Photo, blank=True)
    likes_count = models.BigIntegerField(default=0, null=True)
    comments_count = models.BigIntegerField(default=0, null=True)
    read_count = models.BigIntegerField(default=0, null=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        index_together = (('user', 'created_at'),)

    def __str__(self):
        # 这里是你执行 print(tweet instance) 的时候会显示的内容
        return '{} {}: {}'.format(self.created_at, self.user, self.content)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK