Serializer'ın create () ve ModelViewset'in create () perform_create () ne zaman kullanılacağı


95

django-rest-frameworkBir model nesnenin oluşturulmasıyla ilgili verilen dokümantasyonu netleştirmek istiyorum . Şimdiye kadar bu tür olayların nasıl ele alınacağına dair 3 yaklaşım olduğunu buldum.

  1. Serileştiricinin create()yöntemi. İşte belgeler

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
  2. ModelViewset create()yöntemi. Dokümantasyon

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
  3. ModelViewset perform_create()yöntemi. Dokümantasyon

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

Bu üç yaklaşım, uygulama ortamınıza bağlı olarak önemlidir.

Ancak her create() / perform_create()işlevi NE ZAMAN kullanmalıyız ? Öte yandan, modelviewset create()ve serileştiricilerin tek bir gönderi için iki oluşturma yönteminin çağrıldığına dair bazı hesaplar buldum create().

Umarım herhangi biri açıklamak için bazı bilgilerini paylaşır ve bu kesinlikle geliştirme sürecimde çok yardımcı olacaktır.

Yanıtlar:


125
  1. create(self, validated_data)Tıpkı **validated_datayaptığı gibi her model alanına AND "prod" değerlerini kaydetmeden önce nesneye herhangi bir ekstra ayrıntı eklemek için kullanırsınız . İdeal olarak konuşursak, bu tür "dürtmeyi" yalnızca TEK bir yerde yapmak istersiniz, böylece createsizin yönteminiz CommentSerializeren iyi yerdir. Bunun da ötesinde, hesaplarınızı kendi veritabanınıza kaydetmeden hemen önce kendi tarafında kullanıcı hesapları oluşturmak için harici apis'leri de aramak isteyebilirsiniz. Bu createişlevi ile birlikte kullanmalısınız ModelViewSet. Her zaman düşünün - "İnce görünümler, Kalın serileştiriciler".

Misal:

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)İşlev ModelViewSetde tanımlandığı CreateModelMixinüstüdür sınıfı ModelViewSet. CreateModelMixinana işlevleri şunlardır:

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

Gördüğünüz gibi, yukarıdaki createişlev serileştiricinizde doğrulama çağırma ve doğru yanıtı üretme ile ilgilenir. Bunun arkasındaki güzellik, artık uygulama mantığınızı izole edebilmeniz ve kendinizi sıradan ve tekrarlayan doğrulama çağrıları ve işleme yanıt çıktısıyla ilgilenmeyebilmenizdir :). Bu create(self, validated_data), serileştiricide bulunan (özel uygulama mantığınızın bulunduğu yerde) ile birlikte oldukça iyi çalışır .

  1. Şimdi sorabilirsiniz, neden perform_create(self, serializer)sadece bir satır kodlu ayrı bir fonksiyonumuz var!?!? Bunun arkasındaki ana sebep, saveişlevi çağırırken özelleştirilebilirliğe izin vermektir . Aramadan önce fazladan veri sağlamak isteyebilirsiniz save (örneğinserializer.save(owner=self.request.user) , bizde perform_create(self, serializer)olmasaydı create(self, request, *args, **kwargs), ağır ve sıkıcı işleri yapan mixinlere sahip olma amacını geçersiz kılmanız gerekirdi .

Bu yardımcı olur umarım!


Selam! Bilginizi paylaştığınız için teşekkürler! Hakkında create(self, validated_data)serileştiriciye içinde, bunun veri doğrulama mantığı odaklanır demektir? ve daha fazlası, verilen serileştiricinin verilerini yanıta geri döndürmeye yardımcı olabilir, değil mi?
Roel

1
Hayır, bu noktada, tüm doğrulamanızı zaten geçtiniz. Doğrulanmış verileri bir veritabanına kaydedilmeden hemen önce nasıl özelleştirmek isteyebileceğinizden bahsediyorum. Cevabımda bir örnek vereceğim.
Apoorv Kansal

1
Endişeye gerek yok - sadece daha fazla bağlam sağlamak için bir örnek ekledik.
Apoorv Kansal

1
Evet, nesnenizi veri tabanına kaydedecek son satır bu
Apoorv Kansal

1
Dolayısıyla, createserileştiricinin kendisindeki işlev yalnızca siz bunu yaptığınızda çağrılır serializer.save(). Senin içinde create(self, request)işlev iç ( AccountViewSet), aradığınız olmayan serializer.save()hiç ve bu nedenle, sadece örnek oluşturma Bu çağrıyla oluyor: Account.objects.create_user(**serializer.validated_data).
Apoorv Kansal
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.