Django Rest Framework memperbarui data sebelum membuat serial

Saya ingin setiap pengguna dapat membuat produk mereka sendiri dengan RESTful API saya. Untuk tujuan ini, saya membuat tampilan yang mewarisi ListCreateAPIView. Masalahnya adalah pengguna hanya boleh membuat produk miliknya sendiri, jadi ketika instance model Produk dibuat, saya ingin bidang Pemilik sesuai dengan pengguna yang diautentikasi.

Inilah model Produk saya

class Product(models.Model):
    owner = models.ForeignKey(User)
    name = models.CharField(max_length=30)

Jelas serializer saya adalah:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Product

dan pandangan saya:

class ProductView(generics.ListCreateAPIView):
    queryset = models.Product.objects.all()
    serializer_class = serializers.ProductSerializer
    permission_classes = (IsAuthenticatedOrReadOnly,)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        #serializer.initial_data['owners'] = models.Person.objects.get(user__email=request.user).user_id
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)

        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Seperti yang Anda lihat, saya mencoba memodifikasi "data_awal", tetapi ini adalah QueryDict, yang tidak dapat diubah. Pilihan lain adalah mengubahnya menjadi dict Python dan kemudian menambahkan nilai "pemilik", tetapi dengan melakukan itu saya mendapatkan setiap nilai sebagai daftar (yaitu {'name': ['MyName']}), jadi itu akan menjadi sangat cara yang buruk untuk menyelesaikan masalah, menurut saya ini harus menjadi solusi yang lebih mudah.


person Andres Espinosa    schedule 03.07.2016    source sumber


Jawaban (3)


Anda dapat mengganti perform_create() dan meneruskan pengguna saat ini sebagai owner. Kemudian, ketika instance Product dibuat, kolom owner akan disimpan dengan nilai pengguna saat ini.

class ProductView(generics.ListCreateAPIView):
    queryset = models.Product.objects.all()
    serializer_class = serializers.ProductSerializer
    permission_classes = (IsAuthenticatedOrReadOnly,)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user) # pass the current user as the 'owner'

Selain itu, Anda harus mendefinisikan bidang owner di serializer Anda sebagai read_only. Maka bidang tersebut tidak akan diperlukan selama deserialisasi. Namun, bidang ini akan disertakan dalam keluaran serialisasi.

 class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Product
        extra_kwargs = {'owner': {'read_only':True}} # set 'owner' as read-only field 
person Rahul Gupta    schedule 03.07.2016
comment
Masalahnya adalah fungsi perform_create dipanggil setelah eksekusi is_valid(), dan serializer tidak valid tanpa kolom owner, sehingga fungsi create akan memunculkan pengecualian sebelum perform_create dijalankan. - person Andres Espinosa; 03.07.2016
comment
Anda dapat mendefinisikan bidang owner sebagai read_only di serializer Anda. Maka itu tidak akan diperlukan selama deserialisasi tetapi akan selalu dikembalikan dalam output setelah serialisasi. - person Rahul Gupta; 03.07.2016

Solusi sederhana di bawah ini. owner tidak akan terlihat dalam permintaan GET/POST/PUT dll. tetapi akan ditetapkan secara otomatis ke pengguna yang diautentikasi saat ini.

from rest_framework.serializers import (CurrentUserDefault, HiddenField,
                                        ModelSerializer)

class ProductSerializer(ModelSerializer):
    owner = HiddenField(default=CurrentUserDefault())

    class Meta:
        model = models.Product
person dikamilo    schedule 04.07.2016
comment
itu karya yang cukup bagus. Terima kasih. - person ishak O.; 09.02.2021

Anda dapat meneruskan data awal dalam tampilan dan kemudian menulis ulang nilai default di serializer

dilihat.py

class ItemListCreateView(ListCreateAPIView):

    def get_serializer_context(self):
        return {"delivery_request": self.kwargs['req_pk']}

serializer.py

class ItemCreateSerializer(ModelSerializer):
    delivery_request = CharField(default='')

    def validate_delivery_request(self, value):
        try:
            value = DeliveryRequest.objects.get(
                id=self.context["delivery_request"])
        except DeliveryRequest.DoesNotExist:
            raise ValidationError(
                self.Meta.error_messages['delivery_request_not_found'])
        return value

PS. ini berguna ketika Anda ingin mengisi data bukan Null dari url misalnya

person Artem Bernatskyi    schedule 12.03.2018