Коли використовувати Serializer's create () та ModelViewset create () perform_create ()


97

Я хочу пояснити наведену документацію django-rest-frameworkщодо створення об'єкта моделі. Поки що я виявив, що існує 3 підходи щодо того, як обробляти такі події.

  1. Метод серіалізатора create(). Ось документація

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
  2. Метод ModelViewset create(). Документація

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
  3. Метод ModelViewset perform_create(). Документація

    class SnippetViewSet(viewsets.ModelViewSet):
    
        def perform_create(self, serializer):
            serializer.save(owner=self.request.user)
    

Ці три підходи важливі залежно від середовища вашої програми.

Але КОЛИ нам потрібно використовувати кожну create() / perform_create()функцію ??. З іншого боку, я знайшов деяку інформацію про те, що для одного запиту на публікацію були використані два методи створення - modelviewset create()та serializer create().

Будемо сподіватися, що хтось поділиться своїми знаннями для пояснення, і це, безумовно, буде дуже корисним у моєму процесі розробки.

Відповіді:


126
  1. Ви можете використовувати, create(self, validated_data)щоб додати будь-які додаткові деталі в об'єкт, перш ніж зберігати І "продавати" значення в кожному полі моделі, як **validated_dataце робить. В ідеалі, ви хочете робити таку форму "підштовхування" лише в ОДНОМУ місці, тому createметод у вашому місці CommentSerializerє найкращим. Крім цього, вам може знадобитися також зателефонувати зовнішнім apis для створення облікових записів користувачів на їх боці безпосередньо перед тим, як зберегти ваші облікові записи у власній базі даних. Ви повинні використовувати цю createфункцію разом з ModelViewSet. Завжди думайте - "Тонкі види, товсті серіалізатори".

Приклад:

def create(self, validated_data):
    email = validated_data.get("email", None)
    validated.pop("email") 
    # Now you have a clean valid email string 
    # You might want to call an external API or modify another table
    # (eg. keep track of number of accounts registered.) or even
    # make changes to the email format.

    # Once you are done, create the instance with the validated data
    return models.YourModel.objects.create(email=email, **validated_data)
  1. create(self, request, *args, **kwargs)Функція в ModelViewSetвизначена в CreateModelMixinкласі , який є батьком ModelViewSet. CreateModelMixinОсновними функціями є:

    from rest_framework import status
    from rest_framework.response import Response
    
    
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
    
    def perform_create(self, serializer):
        serializer.save()
    

Як бачите, вищевказана createфункція дбає про перевірку виклику на вашому серіалізаторі та отримання правильної відповіді. Краса за цим полягає в тому, що тепер ви можете ізолювати логіку свого додатка і НЕ турбуватися про буденні та повторювані виклики перевірки та обробку виводу відповіді :). Це працює досить добре у поєднанні з create(self, validated_data)знайденим у серіалізаторі (де може знаходитись ваша логіка конкретного додатка).

  1. Тепер ви можете запитати, чому ми маємо окрему perform_create(self, serializer)функцію лише з одним рядком коду!?!? Ну, головна причина цього полягає в тому, щоб дозволити налаштування під час виклику saveфункції. Можливо, ви захочете надати додаткові дані перед викликом save (наприклад,serializer.save(owner=self.request.user) а якщо у нас їх не було perform_create(self, serializer), вам доведеться перевизначити create(self, request, *args, **kwargs)і це просто перешкоджає тому, щоб міксини виконували важку і нудну роботу.

Сподіваюся, це допомагає!


Привіт! Дякуємо, що поділилися своїми знаннями! Щодо create(self, validated_data)серіалізатора in, це означає, що він зосереджений на логіці перевірки даних? і багато іншого, це може допомогти повернути дані даного серіалізатора назад у відповідь, чи не так?
Roel

1
Ні, на даний момент ви вже пройшли всю свою перевірку. Я говорю про те, як ви можете налаштувати перевірені дані безпосередньо перед тим, як вони будуть збережені в базі даних. Я наведу приклад у своїй відповіді.
Apoorv Kansal

1
Не хвилюйтеся - просто додав приклад, щоб надати більше контексту.
Apoorv Kansal

1
Так, це останній рядок, який збереже ваш об’єкт у базі даних
Apoorv Kansal

1
Тож createфункція в самому серіалізаторі викликається лише тоді, коли ви це робите serializer.save(). У вашій create(self, request)функції всередині ( AccountViewSet), ви не викликаючи serializer.save()взагалі і , отже, тільки створення екземпляра відбувається з цим викликом: Account.objects.create_user(**serializer.validated_data).
Apoorv Kansal
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.