Django rest framework

When do I need many?

  • When constructing serialization, the QuerySet instance of the passed argument needs the many=True argument, even if the QuerySet has a length of 0 or 1
  • When constructing serialization, a model instance (built-in User instance, or custom model instance) of the passed argument needs the many=false argument

The source code parsing

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)
Copy the code

When serialization is performed using the following statement. Serializer = TweetSerializer(QuerySet, many=True) QuerySet is assigned to the BaseSerializer constructor def __init__(self, instance=None, Data =empty, **kwargs): When instance accepts a QuerySet instance, add many=True if instance accepts an instance of a model, such as 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)
Copy the code
class TweetModel(models.Model) :
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    title = models.CharField(max_length=32, verbose_name='title')
    content = models.TextField(verbose_name=The 'body')

    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) :
        # Here's what you get when you run print(Tweet Instance)
        return ' '{} {} {}..format(self.created_at, self.user, self.content)
Copy the code