'How to POST multiple objects in one JSON request?
I am using django-rest-framework and recently I encountered a problem. I need to post such request and get 2 objects created:
{
"lease": 28,
"date": [
{
"from_date": "2021-06-01",
"until_date": "2021-07-01"
},
{
"from_date": "2022-03-22",
"until_date": "2022-04-23"
}
]
}
Model looks like this:
class DateUnavailable(models.Model):
lease = models.ForeignKey(Lease, on_delete=models.CASCADE, blank=False, null=False)
from_date = models.DateField(blank=True, null=True)
until_date = models.DateField(blank=True, null=True)
How that can be accomplished? I tried Serializer(many=true) in views.py, but it does not work
Solution 1:[1]
I had the same issue you are having, then what I have done was create a model that had the fields as a ManyToManyField()
to allow the creation of multiple nested fields:
Bear in mind that the default DRF forms will not allow multiple posts. You will need to pass them directly as json format.
models
class ProfileProperty(models.Model):
gender = models.CharField(....)
height = models.DecimalField(..)
width = models.DecimalField(...)
....
class Profile(models.Model):
name = models.CharField(User, on_delete=models.CASCADE)
property = models.ManyToManyField(ProfileProperty) # <------------------------
def __str__(self):
return self.name
Serializers
imports ...
Class ProfilePropertySerializer(serializer.ModelSerializer):
class Meta:
model = ProfileProperty
fields = "__all__"
Class ProfileSerializer(serializer.ModelSerializer):
property = ProfilePropertySerializer(many=True)
class Meta:
model = Profile
fields = "__all__"
def create(self, validate_data):
# get the value from the payload.
properties = validated_data.pop('property')
# Add (all) the value from payload to the Profile model.
profile_instance = Profile.objects.create(**validated_data)
# Loop the values that were passed inside of property fields from payload.
for property in properties:
# Add normally the fields of "this payload" to the Property model.
property_instance = Property.objects.create(**property)
# Here is where the magic begins:
# Get the property_instance and passes all the payloads.id.
# and add them to profile_instance as it should be.
profile_instance.property.add(property_instance.id)
# save the values.
profile_instance.save()
return profile_instance
def update(self, instance, validate_data):
# do awesome stuff here... ;)
Payload
[
{
"id":1,
"name":"John Smith",
"property":[
{
"gender":"Male",
"height": 1.72,
"width":null
},
{
"gender":"Male",
"height": 1.90,
"width":null
},
{
"gender":"Male",
"height": 1.72,
"width":null
},
]
}
]
Solution 2:[2]
Make your payload a JSON array. It should work with many=True
[
{
"lease": 28,
"from_date": "2021-06-01",
"until_date": "2021-07-01"
},
{
"lease": 28,
"from_date": "2022-03-22",
"until_date": "2022-04-23"
}
]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | MjZac |