Kapan menggunakan serializer create () dan ModelViewset's create () perform_create ()

97

Saya ingin mengklarifikasi dokumentasi yang diberikan django-rest-frameworktentang pembuatan objek model. Sejauh ini saya menemukan ada 3 pendekatan tentang bagaimana menangani kejadian tersebut.

  1. Metode Serializer create(). Berikut dokumentasinya

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
  2. create()Metode ModelViewset . Dokumentasi

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
  3. perform_create()Metode ModelViewset . Dokumentasi

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

Ketiga pendekatan ini penting bergantung pada lingkungan aplikasi Anda.

Tapi KAPAN kita perlu menggunakan setiap create() / perform_create()fungsi ??. Di sisi lain saya menemukan beberapa akun yang dua metode create dipanggil untuk permintaan posting tunggal modelviewset create()dan serializer's create().

Semoga ada yang mau berbagi sedikit ilmunya untuk dijelaskan dan ini pasti akan sangat membantu dalam proses pengembangan saya.

Roel
sumber

Jawaban:

126
  1. Anda akan menggunakan create(self, validated_data)untuk menambahkan detail tambahan ke objek sebelum menyimpan nilai AND "prod" ke setiap bidang model seperti yang **validated_datadilakukan. Idealnya, Anda ingin melakukan bentuk "dorongan" ini hanya di SATU lokasi sehingga createmetode di tempat Anda CommentSerializeradalah yang terbaik. Selain itu, Anda mungkin juga ingin memanggil API eksternal untuk membuat akun pengguna di pihak mereka sebelum menyimpan akun Anda ke dalam database Anda sendiri. Anda harus menggunakan createfungsi ini bersama dengan ModelViewSet. Selalu berpikir - "Tampilan tipis, serializers Tebal".

Contoh:

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. The create(self, request, *args, **kwargs)fungsi dalam ModelViewSetdidefinisikan dalam CreateModelMixinkelas yang merupakan induk dari ModelViewSet. CreateModelMixinFungsi utamanya adalah sebagai berikut:

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

Seperti yang Anda lihat, createfungsi di atas menangani validasi panggilan pada pembuat serial Anda dan menghasilkan respons yang benar. Keindahan di balik ini, adalah bahwa Anda sekarang dapat mengisolasi logika aplikasi Anda dan TIDAK mengkhawatirkan diri Anda sendiri tentang panggilan validasi yang biasa dan berulang serta menangani keluaran respons :). Ini bekerja cukup baik sehubungan dengan yang create(self, validated_data)ditemukan di serializer (di mana logika aplikasi spesifik Anda mungkin berada).

  1. Sekarang Anda mungkin bertanya, mengapa kita memiliki perform_create(self, serializer)fungsi terpisah hanya dengan satu baris kode!?!? Nah, alasan utama di balik ini adalah untuk memungkinkan penyesuaian saat memanggil savefungsi. Anda mungkin ingin memberikan data tambahan sebelum menelepon save (sepertiserializer.save(owner=self.request.user) dan jika kami tidak memilikinya perform_create(self, serializer), Anda harus mengganti create(self, request, *args, **kwargs)dan itu hanya akan mengalahkan tujuan membuat mixin melakukan pekerjaan yang berat dan membosankan.

Semoga ini membantu!

Apoorv Kansal
sumber
Hai! Terima kasih telah membagikan pengetahuan Anda! Tentang create(self, validated_data)di serializer, artinya berfokus pada logika validasi data? dan lebih dari itu dapat membantu mengembalikan data serializer yang diberikan kembali ke respon kan?
Roel
1
Tidak, saat ini Anda sudah lulus semua validasi. Saya berbicara tentang bagaimana Anda mungkin ingin menyesuaikan data yang divalidasi sebelum disimpan ke dalam database. Saya akan membuat contoh dalam jawaban saya.
Apoorv Kansal
1
Jangan khawatir - tambahkan saja contoh untuk memberikan lebih banyak konteks.
Apoorv Kansal
1
Ya, itulah baris terakhir yang akan menyimpan objek Anda ke database
Apoorv Kansal
1
Jadi createfungsi di serializer itu sendiri hanya dipanggil saat Anda melakukannya serializer.save(). Dalam Anda create(self, request)fungsi dalam ( AccountViewSet), Anda tidak menelepon serializer.save()sama sekali dan oleh karena itu, satu-satunya contoh penciptaan yang terjadi dengan panggilan ini: Account.objects.create_user(**serializer.validated_data).
Apoorv Kansal