I am using 2 serializers for validating this request:
{
"name":"Dade Waste Facility",
"email":"example@mailinator.com",
"mobile":"1234567",
"street":"Street 1",
"city":"Miami",
"zipcode":"123456",
"state":"Florida",
"material_types": [{
"name": "Metal",
"cost_per_ton": 20
},
{
"cost_per_ton": 50,
"name": "Food"
}]
}
Django code:
class MaterialTypeSerializer(serializers.Serializer):
name = serializers.CharField(
required=True,
max_length=255,
error_messages={
"required": "Material type name is required.",
"max_length": "Material type name can be maximum 255 characters.",
},
)
cost_per_ton = serializers.IntegerField(
required=True,
error_messages={"required": "Material type cost per ton is required.",},
)
class Meta:
fields = "__all__"
class WasteFacilityPostSerializer(serializers.ModelSerializer):
name = serializers.CharField(
required=True,
max_length=255,
error_messages={
"required": "Name is required.",
"max_length": "Name can be maximum 255 characters.",
},
)
contact_person_name = serializers.CharField(
required=False,
max_length=255,
error_messages={
"max_length": "Contact person name can be maximum 255 characters.",
},
)
email = serializers.EmailField(
required=False,
max_length=255,
error_messages={
"invalid": "Email address not valid.",
"max_length": "Email can be maximum 255 characters.",
},
)
mobile = serializers.CharField(
required=True,
validators=[
RegexValidator(
regex=r"^\d{10,14}$",
message="Phone number must be entered in format: '+999999999'. Up to 14 digits allowed.",
)
],
max_length=15,
error_messages={
"required": "Mobile is required.",
"max_length": "Mobile can be maximum 14 digits.",
},
)
street = serializers.CharField(
required=True,
max_length=255,
error_messages={
"required": "Street is required.",
"max_length": "Street can be maximum 255 characters.",
},
)
suite = serializers.CharField(
required=False,
max_length=255,
error_messages={"max_length": "Suite can be maximum 255 characters.",},
)
city = serializers.CharField(
required=True,
max_length=255,
error_messages={
"required": "City is required.",
"max_length": "City can be maximum 255 characters.",
},
)
zipcode = serializers.CharField(
required=True,
max_length=10,
error_messages={
"required": "Zipcode is required.",
"max_length": "Zipcode can be maximum 10 digits.",
},
)
state = serializers.CharField(
required=True,
max_length=255,
error_messages={
"required": "State is required.",
"max_length": "State can be maximum 255 characters.",
},
)
material_types = MaterialTypeSerializer(
required=True,
many=True,
error_messages={"required": "Material type is required."},
)
class Meta:
model = WasteFacility
exclude = []
def validate_name(self, value):
waste_facility = WasteFacility.objects
if self.instance:
waste_facility = waste_facility.exclude(pk=self.instance.pk)
if waste_facility.filter(name__iexact=value):
raise serializers.ValidationError(
"Waste facility with this name already exists."
)
return value
def validate_email(self, value):
waste_facility = WasteFacility.objects
if self.instance:
waste_facility = waste_facility.exclude(pk=self.instance.pk)
if waste_facility.filter(email__iexact=value):
raise serializers.ValidationError(
"Waste facility with this email already exists."
)
return value
def validate_mobile(self, value):
if validate_phone_number(value) is None:
waste_facility = WasteFacility.objects
if self.instance:
waste_facility = waste_facility.exclude(pk=self.instance.pk)
if waste_facility.filter(mobile__iexact=value):
raise serializers.ValidationError(
"Waste facility with this phone number already exists."
)
return value
def validate_material_types(self, attrs):
if len(attrs) == 0:
raise serializers.ValidationError("At least one material type is required.")
return attrs
def create(self, validated_data):
try:
with transaction.atomic():
material_types = validated_data.pop("material_types")
instance = WasteFacility.objects.create(**validated_data)
print(material_types)
for material_type in material_types:
for key, value in material_type.items():
print(key, value)
raise Exception("This is a test exception.")
return instance
except DatabaseError as database_error:
return None
If you see the create method of WasteFacilitySerializer you'll see that i am printing material_types property. This is what I see:
[OrderedDict([('name', 'Metal'), ('cost_per_ton', 20)]), OrderedDict([('name', 'Food'), ('cost_per_ton', 50)])]
How to get list of dictionaries instead of ordereddict to that it will be easy to traverse? As I want to sync this data with one of my ManyToMany tables. Is this the right way to do it or there is a better way to implement this?
This is what I did to get dict from list of ordered dict.
for material_type in material_types:
material_type = dict(material_type)
Iterated the material_types list of ordered dict and converted them to dict.