Reputation: 566
I am a newbie in Django, and I had implemented a one-to-many relationship, however one fieled which is nested is null.
When I post destinations
is null in the response section. Below is my response section :
{
"id": 7,
"name": "Germany tour",
"description": "This is a fascinating tour to take",
"price": "30.0",
"destinations": null,
"capacity": 10
}
This is the way I am posting in the Body section in postman :
{
"name": "Germany tour",
"description": "This is a fascinating tour to take",
"price": 30.0,
"destinations": [
{
"location":"Germany",
"tour_type":"Adventure",
"danger_type":"Medium"
}
],
"capacity": 10
}
Then, below is my models file :
from django.db import models
class Destinations(models.Model):
location = models.CharField(max_length=20)
tour_type = models.CharField(max_length=20)
danger_type = models.CharField(max_length=20)
class Meta:
unique_together = ['location', 'tour_type']
class TourPackages(models.Model):
name = models.CharField(max_length=50)
description = models.TextField()
price = models.DecimalField(max_digits=9, decimal_places=1)
destinations = models.ForeignKey(Destinations, related_name="destinations", on_delete=models.CASCADE)
capacity = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
Then, my serializers file :
from rest_framework import serializers
from .models import TourPackages, Destinations
class DestinationSerializer(serializers.ModelSerializer):
class Meta:
model = Destinations
fields = ['tour_type', 'danger_type']
class TourPackagesSerializer(serializers.ModelSerializer):
destinations = DestinationSerializer(many=True)
class Meta:
model = TourPackages
fields = ['id', 'name', 'description', 'price', 'destinations', 'capacity']
def create(self, validated_data):
destination_data = validated_data.pop("destinations")
location = TourPackages.objects.create(**validated_data)
for dest_data in destination_data:
Destinations.objects.create(location=location, **dest_data)
return location
Then finally my views file :
from rest_framework import generics
from .models import TourPackages
from .serializer import TourPackagesSerializer
class TourList(generics.ListCreateAPIView):
queryset = TourPackages.objects.all()
serializer_class = TourPackagesSerializer
class TourDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = TourPackages.objects.all()
serializer_class = TourPackagesSerializer
What I want is to post all the data and comes back in response
Upvotes: 2
Views: 1457
Reputation: 424
You need to create Destinations
object first in order to assign them in case of ForeignKey
. From the sample data you have posted it implies that you can have multiple destinations
and you have on_delete=models.CASCADE
set on that. Suppose for a particular tour you have4
destinations and you decide to delete two of them, then models.CASCADE
will try to delete your tours
object. If this happens where will the remaining 2
destinations object point to? Database integrity
will be lost. So Django
will not allow this. You can fix by changing ForeignKey
To ManyToManyField
.
And your TourPackagesSerializer
should be like this:
Building on the answer from Ananya:
class TourPackagesSerializer(serializers.ModelSerializer):
destinations = DestinationSerializer(many=True)
class Meta:
model = TourPackages
fields = ['id', 'name', 'description', 'price', 'destinations', 'capacity']
def create(self, validated_data):
destination_data = validated_data.pop('destinations')
dest_obj_list = []
for dest_data in destination_data:
dest_obj = Destinations.objects.create(**dest_data)
dest_obj_list.append(dest_obj)
location = TourPackages.objects.create(**validated_data)
location.destinations.set(dest_obj_list)
location.save()
return location
Upvotes: 3
Reputation: 101
In the create method you are creating the destination objects but not setting the Foreign Key in location. Try this:
def create(self, validated_data):
destination_data = validated_data.pop('destinations')
dest_obj_list = []
for dest_data in destination_data:
dest_obj = Destinations.objects.create(location=location, **dest_data)
dest_obj_list.append(dest_obj)
location = TourPackages.objects.create(**validated_data)
location.destinations.set(dest_obj_list)
location.save()
Upvotes: 0