Khi nào sử dụng create () của Serializer và create () performance_create () của ModelViewset


97

Tôi muốn làm rõ tài liệu đã cho django-rest-frameworkvề việc tạo đối tượng mô hình. Cho đến nay, tôi thấy rằng có 3 cách tiếp cận về cách xử lý các sự kiện như vậy.

  1. create()Phương pháp Serializer . Đây là tài liệu

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
  2. create()Phương thức ModelViewset . Tài liệu

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
  3. perform_create()Phương thức ModelViewset . Tài liệu

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

Ba cách tiếp cận này quan trọng tùy thuộc vào môi trường ứng dụng của bạn.

Nhưng KHI NÀO chúng ta cần sử dụng từng create() / perform_create()chức năng ??. Mặt khác, tôi tìm thấy một số tài khoản mà hai phương thức tạo được gọi cho một bài đăng yêu cầu của modelviewset create()và serializer create().

Mong rằng có ai chia sẻ chút kiến ​​thức để giải thích và chắc chắn điều này sẽ rất hữu ích trong quá trình phát triển của tôi.

Câu trả lời:


126
  1. Bạn sẽ sử dụng create(self, validated_data)để thêm bất kỳ chi tiết bổ sung nào vào đối tượng trước khi lưu các giá trị AND "prod" vào mỗi trường mô hình giống như cách **validated_datalàm. Nói một cách lý tưởng, bạn chỉ muốn thực hiện hình thức “thúc đẩy” này ở MỘT địa điểm nên createphương pháp của bạn CommentSerializerlà nơi tốt nhất. Trên hết, bạn cũng có thể gọi các apis bên ngoài để tạo tài khoản người dùng cho họ ngay trước khi lưu tài khoản của bạn vào cơ sở dữ liệu của riêng bạn. Bạn nên sử dụng createchức năng này kết hợp với ModelViewSet. Luôn nghĩ - "Lượt xem mỏng, Bộ tuần tự dày".

Thí dụ:

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. Các create(self, request, *args, **kwargs)chức năng trong ModelViewSetđược định nghĩa trong CreateModelMixinlớp học mà là phụ huynh của ModelViewSet. CreateModelMixinCác chức năng chính của nó là:

    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()
    

Như bạn có thể thấy, createhàm trên đảm nhận việc gọi xác thực trên bộ nối tiếp của bạn và tạo ra phản hồi chính xác. Vẻ đẹp đằng sau điều này là giờ đây bạn có thể cô lập logic ứng dụng của mình và KHÔNG quan tâm đến bản thân về các cuộc gọi xác thực thông thường và lặp đi lặp lại và xử lý đầu ra phản hồi :). Điều này hoạt động khá tốt trong việc kết hợp với create(self, validated_data)bộ tuần tự được tìm thấy (nơi logic ứng dụng cụ thể của bạn có thể nằm).

  1. Bây giờ bạn có thể hỏi, tại sao chúng ta có một perform_create(self, serializer)chức năng riêng biệt chỉ với một dòng mã!?!? Lý do chính đằng sau điều này là để cho phép khả năng tùy chỉnh khi gọi savehàm. Bạn có thể muốn cung cấp thêm dữ liệu trước khi gọi save (giống nhưserializer.save(owner=self.request.user) và nếu chúng tôi không có perform_create(self, serializer), bạn sẽ phải ghi đè create(self, request, *args, **kwargs)và điều đó chỉ làm mất đi mục đích của việc các mixin thực hiện công việc nặng nhọc và nhàm chán.

Hi vọng điêu nay co ich!


Chào! Cảm ơn bạn đã chia sẻ kiến ​​thức của bạn! Về bộ create(self, validated_data)tuần tự, nó có nghĩa là nó tập trung vào logic xác thực dữ liệu? và hơn thế nữa, nó có thể giúp trả lại dữ liệu của trình nối tiếp đã cho trở lại phản hồi phải không?
Roel

1
Không, tại thời điểm này, bạn đã vượt qua tất cả các xác nhận của mình. Tôi đang nói về cách bạn có thể muốn tùy chỉnh dữ liệu đã được xác thực ngay trước khi nó được lưu vào cơ sở dữ liệu. Tôi sẽ làm một ví dụ trong câu trả lời của tôi.
Apoorv Kansal

1
Đừng lo lắng - chỉ cần thêm một ví dụ để cung cấp thêm ngữ cảnh.
Apoorv Kansal

1
Vâng đó là dòng cuối cùng mà sẽ tiết kiệm được đối tượng của bạn vào cơ sở dữ liệu
Apoorv Kansal

1
Vì vậy, bản thân createhàm trong bộ tuần tự chỉ được gọi khi bạn thực hiện serializer.save(). Trong của bạn create(self, request)bên trong function ( AccountViewSet), bạn không được gọi serializer.save()ở tất cả và do đó, việc tạo ra trường hợp duy nhất đang xảy ra với cuộc gọi này: Account.objects.create_user(**serializer.validated_data).
Apoorv Kansal
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.