Как написать функцию POST для вложенных сериализаторов Django

#python #json #django #serialization #django-rest-framework

#python #json #django #сериализация #django-rest-framework

Вопрос:

Я не могу написать метод .create для этого вложенного serailizer. Я хочу создать строку назначения для каждой новой встречи, а для таблицы appointment_detail я хочу создать столько строк, сколько выбрано служб.

мой models.py

 class Service(models.Model):
category = models.ForeignKey(Categories, on_delete=models.CASCADE,null=True, related_name='services')
service_name = models.CharField(max_length=100)
time = models.PositiveIntegerField(default=0)
price = models.DecimalField(max_digits=10, decimal_places=2, null=False)

def __str__(self):
    return self.service_name   ' in '   str(self.category)

class Appointment_Status(models.Model):
status = models.CharField(max_length=15)

def __str__(self):
    return self.status

class Appointment(models.Model):
"""This is the model where all the orders/Appointments will be saved"""
user        = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
zorg        = models.ForeignKey(Zorg, on_delete=models.CASCADE, null=True)
branch      = models.ForeignKey(Zorg_Branche, on_delete=models.CASCADE,null=True, related_name='branch')
timestamp   = models.DateTimeField(auto_now_add=True, blank=True)
status      = models.ForeignKey(Appointment_Status, on_delete=models.CASCADE, null=True)
totaltime   = models.PositiveIntegerField(default=0)
total_price = models.DecimalField(decimal_places=2, max_digits=10, default=0)


def __str__(self):
    return  str(self.user)   ' -> '    str(self.zorg)

class AppointmentDetail(models.Model):
appointment  = models.ForeignKey(Appointment, 
on_delete=models.CASCADE,null=True,related_name='appointment')
related_name='category')
service      = models.ForeignKey(Service, on_delete=models.CASCADE,null=True, related_name='service')

def __str__(self):
    return str(self.appointment)   '  '   str(self.service)
  

в serializers.py

 class UserAppointmentSerializer(serializers.ModelSerializer):
class Meta:
    model = User
    fields = [
                'id',
                'first_name',
                'last_name',
                'email_id',
                'mobile_number',
                'birthdate',
                'photo_url',
                'gender',
              ]

class ZorgBranchAppointmentSerializer(serializers.ModelSerializer):
class Meta:
    model = Zorg_Branche
    exclude = ['id', 'zorg']

class CategoryAppointmentSerializer(serializers.ModelSerializer):
"""
This serailizer is to serialize and deserailize category model
"""
class Meta:
    model = Categories
    fields = ['category_name']

class ServiceAppointmentSerializer(serializers.ModelSerializer):
"""
This is a serializer to serializer and deserailize service serailizer.
"""
category = CategoryAppointmentSerializer()
class Meta:
    model = Service
    exclude = ['id']

class ZorgAppointmentSerializer(serializers.ModelSerializer):
class Meta:
    model = Zorg
    fields = [
                'id',
                 'name',
                 'salon_email_id',
                 'website'
             ]

class AppointmentDetailSerializer(serializers.ModelSerializer):


service = ServiceAppointmentSerializer()
class Meta:
    model = AppointmentDetail
    exclude = ['id', 'appointment', ]

class AppointmentStatusSerilizer(serializers.ModelSerializer):

class Meta:
    model = Appointment_Status
    fields = ['status']

class AppointmentSerializer(serializers.ModelSerializer):
appointment = AppointmentDetailSerializer(many=True)
status = AppointmentStatusSerilizer()
user = UserAppointmentSerializer()
zorg = ZorgAppointmentSerializer()
branch = ZorgBranchAppointmentSerializer()
class Meta:
    model = Appointment
    fields = [
            'id', 
            'status',
            'appointment',
            'user',
            'zorg',
            'branch',
            'timestamp',
            'totaltime',
            'total_price'
        ]

def create(self, validated_data):
    user = validated_data.pop('user')
    zorg = validated_data.pop('zorg')
    status = validated_data.pop('status')
    branch = validated_data.pop('branch')
    appointment = validated_data.pop('appointment')

    for app in appointment:
        service = app.pop('service')
        category = service.pop('category')
        category_instance = Categories.objects.get(**category)
        service_instance = Service.objects.get(category = category_instance, **service)
        appointment_detail = AppointmentDetail.objects.create(service=service_instance)

    user_instance = User.objects.get(**user)
    zorg_instance = Zorg.objects.get(**zorg)
    status_instance = Appointment_Status.objects.get(**status)
    branch_instance = Zorg_Branche.objects.get(**branch)
   
    writable_data = Appointment.objects.create( user = user_instance, zorg = zorg_instance, status = 
    status_instance, branch = branch_instance, **validated_data)


    return writable_data
  

Я могу заставить работать все остальное, кроме назначения. Я не могу передать часть назначения записываемым данным из цикла for. Вот JSON, который я хочу использовать.

 {
    "id": 2,
    "status": {
        "status": "Pending"
    },
    "appointment": [
        {
            "service": {
                "category": {
                    "category_name": "Spa"
                },
                "service_name": "normal spa",
                "time": 0,
                "price": "700.00"
            }
        },
        {
            "service": {
                "category": {
                    "category_name": "Facial"
                },
                "service_name": "Normal Facial",
                "time": 0,
                "price": "1500.00"
            }
        }
    ],
    "user": {
        "id": 23,
        "first_name": "Sample",
        "last_name": "Sample",
        "email_id": "sample@gmail.com",
        "mobile_number": "9999999999",
        "birthdate": "2001-01-22",
        "photo_url": "",
        "gender": 1
    },
    "zorg": {
        "id": 53,
        "name": "Sample",
        "salon_email_id": "sample@gmail.com",
        "website": "http://sample.in"
    },
    "branch": {
        "address": "Sample Plaza",
        "city": "Sample",
        "state": "Sample Pradesh",
        "country": "India",
        "zip_code": "462003"
    },
    "timestamp": "2020-09-25T20:13:28.806558Z",
    "totaltime": 0,
    "total_price": "0.00"
}
  

Комментарии:

1. Я хотел бы предложить изменить подход, потому что специфика производительности действительно связана с проводами. Вы должны обрабатывать детали назначения в views.py просто переопределив метод perform_create, если вы используете общие представления и обрабатываете всю вашу проверку в вашем сериализаторе. Вы должны использовать массовое создание post для всей проверки, а не для одной операции создания базы данных.

2. @AshishGupta какие проблемы с производительностью мы здесь рассматриваем? Кроме того, я не очень разбираюсь в drf, можете ли вы порекомендовать мне какие-нибудь ресурсы?

3. Если вы посмотрите в AppointmentSerializer с помощью метода create, метод имеет цикл for и обращение к БД для каждой детали. Вместо этого используйте метод массового создания ( medium.com/swlh /… ). В идеале цикл и запросы к БД всегда являются дорогостоящими операциями. Мы всегда должны избегать такой проблемы и делать наш код более эффективным.