I want to create a post request using DRF. The problem is i cant figure out how to properly make create method for a serializer in that case, so it eats an instance
I can create for example crane or chassis instance for further “Truck” creation, but can’t create a Truck instance, cause it says Chassis and Crane must be a dictionary, but I want to pass an instance of these
models.py
class Chassis(models.Model):
id = models.BigAutoField(primary_key=True)
brand = models.CharField(max_length=255)
model = models.CharField(max_length=255)
class ChassisProperty(models.Model):
id = models.BigAutoField(primary_key=True)
chassis = models.ForeignKey(Chassis, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
value = models.CharField(max_length=255)
class Crane(models.Model):
id = models.BigAutoField(primary_key=True)
brand = models.CharField(max_length=255)
model = models.CharField(max_length=255)
class CraneProperty(models.Model):
id = models.BigAutoField(primary_key=True)
crane = models.ForeignKey(Crane, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
value = models.CharField(max_length=255)
class Trucks(models.Model):
class TruckTypes(models.TextChoices):
FLATBED = 'FB', 'Бортовой автомобиль'
TOW = 'TW', 'Тягач'
DRILLING_MACHINE = 'DM', 'Буровая машина'
LOG_CARRIER = 'LC', 'Сортиментовоз'
MOBILE_WORKSHOP = 'MW', 'Передвижная мастерская'
SCRAP_TRUCK = 'ST', 'Ломовоз'
MULTILIFT = 'ML', 'Мультилифт'
DUMP_TRUCK = 'DT', 'Самосвал'
TANK_TRUCK = 'TT', 'Автоцистерна'
LOADER = 'LR', 'Погрузчик'
class WheelBases(models.TextChoices):
SIX_TO_FOUR = '64', '6x4'
SIX_TO_SIX = '66', '6x6'
FOUR_TO_FOUR = '44', '4x4'
EIGHT_TO_FOUR = '84', '8x4'
FOUR_TO_TWO = '42', '4x2'
id = models.BigAutoField(primary_key=True)
chassis = models.ForeignKey(Chassis, on_delete=models.CASCADE)
crane = models.ForeignKey(Crane, on_delete=models.CASCADE)
truck_type = models.CharField(max_length=2, choices=TruckTypes.choices)
wheel_base = models.CharField(max_length=2, choices=WheelBases.choices)
class TruckProperty(models.Model):
id = models.BigAutoField(primary_key=True)
truck = models.ForeignKey(Trucks, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
value = models.CharField(max_length=255)
Serializers.py
import json
from rest_framework import serializers
from .models import *
class ChassisPropertySerializer(serializers.ModelSerializer):
class Meta:
model = ChassisProperty
exclude = ('chassis',)
class ChassisSerializer(serializers.ModelSerializer):
chassisproperty_set = ChassisPropertySerializer(many=True)
class Meta:
model = Chassis
fields = '__all__'
def create(self, validated_data):
chassis_data = validated_data.pop('chassisproperty_set')
chassis = Chassis.objects.create(**validated_data)
for data in chassis_data:
ChassisProperty.objects.create(chassis=chassis, **data)
return chassis
class CranePropertySerializer(serializers.ModelSerializer):
class Meta:
model = CraneProperty
exclude = ('crane',)
class CraneSerializer(serializers.ModelSerializer):
craneproperty_set = CranePropertySerializer(many=True)
class Meta:
model = Crane
fields = '__all__'
def create(self, validated_data):
crane_data = validated_data.pop('craneproperty_set')
crane = Crane.objects.create(**validated_data)
for data in crane_data:
CraneProperty.objects.create(crane=crane, **data)
return crane
class TruckPropertySerializer(serializers.ModelSerializer):
class Meta:
model = TruckProperty
exclude = ('truck',)
class TruckSerializer(serializers.ModelSerializer):
truckproperty_set = TruckPropertySerializer(many=True)
chassis = ChassisSerializer(many=False)
crane = CraneSerializer(many=False)
truck_type = serializers.CharField(source='get_truck_type_display')
wheel_base = serializers.CharField(source='get_wheel_base_display')
class Meta:
model = Trucks
fields = '__all__'
def create(self, validated_data):
trucks_data = validated_data.pop('truckproperty_set')
print(validated_data)
truck = Trucks.objects.create(**validated_data)
for truck_data in trucks_data:
TruckProperty.objects.create(truck=truck, **truck_data)
return truck
And views.py
from rest_framework import viewsets
from .serializers import *
from .models import *
class TrucksViewSet(viewsets.ModelViewSet):
queryset = (Trucks.objects.prefetch_related(
'chassis__trucks_set',
'chassis__chassisproperty_set',
'crane__trucks_set',
'crane__craneproperty_set'
).all())
serializer_class = TruckSerializer
class ChassisViewSet(viewsets.ModelViewSet):
queryset = Chassis.objects.prefetch_related('chassisproperty_set')
serializer_class = ChassisSerializer
class CraneViewSet(viewsets.ModelViewSet):
queryset = Crane.objects.prefetch_related('craneproperty_set')
serializer_class = CraneSerializer