简体   繁体   中英

django rest framework: How to not allow validation on a nested serializer data?

I have a serializer BookSerializer of model Book with a nested PageSerializer of model Page . Updating of a Book instance involves deleting all its Page instances followed by creation of these Page instances, maybe with or without this updation involving some new data of pages or nothing or existing.

But my Book model holds a constraint where each Book instance can only have max 100 pages each. And the validation check is done inside the PageSerializer 's validate method. I have another reason to do this here:

def validate(self, attrs):
    #some logic here
    raise some error if book instance already has 100 pages or if it will have more than 100 pages when combined with new pages when added.

The update method definition of a serializer or say BookSerializer is:

def update(self, instance, validated_data):
    ...
    ...

So, the data being sent to update is already being validated and can be accessed as validated_data inside the update method.

Now, here's the problem. The nested serializer PageSerializer has a validate method which checks how many pages of that Book instance are already there and validates against them.

Let B be an instance of Book already having 100 pages. If I try to udate B without any changes, the data sent is still checked for validation in the BookSerializer , passing its pages data to PageSerializer and then finally passing the validated_data to update(self, instance, val;idated_data) method.

My questions are:

  • How to delete all pages of B before validating data of pages sent for updation of B ?
  • Or How to bypass validation of the nested serializer? Only validate the serializer and will take care of the validation of the nested serializer inside the update method of the parent serializer before saving.

I recommend you to you to delete pages in update(**kwargs) method of BookSerializer. In validation method of PageSerializer you should validate received data(you should not consider existed pages as a sequence you will delete all them ). It is a case for only fully overriding pages of existed book. But when you want to update them you should also return id (you should add id in PageSerializer in order nested serializer can identify that you are updating an instance) of pages. So validation will be required in order to update.

Request body should be like this:

{
   'book_title': 'TITLE'
   'pages':[
           {'id': 3, 'title': 'TITLE', 'body': 'BODY'},
           {'title': 'TITLE', 'body': 'BODY'}, ...
    ]
    ....
}
class PageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Page
        fields =['id', .....]

class Book(serializers.ModelSerializer):
    pages = PageSerializer(many=True)

    class Meta:
        model = Book
        fields = ['id', 'pages', ....]

    def validate_pages(self, values): # here values will be as [{...},{...},..]
        obj_list = list()
        for value in values:
            pk = value.pop('id', None)
            if pk:
               try:
                  page = Page.objects.get(pk=pk)
                  for k, v in value.items():
                      setattr(page, key, value)
                  obj_list.append(page)
               except Page.DoesNotExists():
                  # handle by yourself, skip or raise error
            else:
                obj_list.append(Page(**value))
         # here you can validate length also
         return obj_list

And in create(self, validated_data) and update(self, instance, validated_data) you get pages as object list. So you can delete using this:

pages = validated_data['pages']
page_ids = [page.pk for page in pages if page.pk] # it get all ids from list
if page_ids:
   Page.objects.filter(book=instance).exclude(pk__in=page_ids).delete() it can be applicable only for updating

And simple creation using bulk or iteration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM