django rest framework: Как запретить проверку вложенных данных сериализатора? - PullRequest
0 голосов
/ 23 сентября 2018

У меня есть сериализатор BookSerializer модели Book с вложенной PageSerializer модели Page.Обновление экземпляра Book включает удаление всех его экземпляров Page с последующим созданием этих Page экземпляров, возможно, с этим обновлением или без него, включающее какие-то новые данные страниц или ничего или существующее.

Но мойМодель Book содержит ограничение, в котором каждый экземпляр Book может иметь только максимум 100 страниц каждая.И проверка правильности выполняется в методе PageSerializer validate.У меня есть еще одна причина сделать это здесь:

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.

Определение метода обновления сериализатора или, скажем, BookSerializer:

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

Итак, данные, отправляемые на обновление,уже проверяется и может быть доступен как validated_data в методе update.

Теперь вот проблема.Вложенный сериализатор PageSerializer имеет метод validate, который проверяет, сколько страниц этого экземпляра Book уже существует, и проверяет их.

Пусть B будет экземпляром Book, уже имеющим 100 страниц.Если я попытаюсь обновить B без каких-либо изменений, отправленные данные по-прежнему проверяются для проверки в BookSerializer, передавая данные своих страниц в PageSerializer и, наконец, передавая метод validated_data в update(self, instance, val;idated_data).

Мои вопросы:

  • Как удалить все страницы B перед проверкой данных страниц, отправленных для обновления B?
  • Или Как обойти проверкувложенного сериализатора?Проверяйте только сериализатор и позаботьтесь о проверке вложенного сериализатора в методе обновления родительского сериализатора перед сохранением.

1 Ответ

0 голосов
/ 23 сентября 2018

Я рекомендую вам удалить страницы в update(**kwargs) методе BookSerializer.При методе проверки PageSerializer вы должны проверять полученные данные (вы не должны рассматривать существующие страницы как последовательность, вы удалите все их ).Это относится только к полностью переписывающим страницам существующей книги.Но когда вы хотите обновить их, вы также должны вернуть id (вы должны добавить id в PageSerializer, чтобы вложенный сериализатор мог определить, что вы обновляете экземпляр) страниц.Таким образом, для обновления потребуется подтверждение.

Тело запроса должно быть таким:

{
   '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

И в create(self, validated_data) и update(self, instance, validated_data) вы получаете страницы в виде списка объектов.Таким образом, вы можете удалить, используя это:

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

И простое создание, используя объем или итерацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...