I am using DRF as a back end to a jscript front end. In the front end, I am handling a hierarchical json object which defines a Flight:
Flight
|- Sections (10-40 sections per flight)
|---- Figures (0 to 10 figures per section)
|------- Arestis (0 to 4 arestis per figure)
|- FlightPath (one large json structure per flight)
I am having problems with creating and updating the flight and its children/grandchildren. I have a method working, which loops through the flight, creating records for each level, but it is very slow and perhaps neeeds wrapping in a transaction (I use mySQL server.) The update does a similar thing.
Is there a better way?
I have five classes in the model (truncated). Flight Path is in a seperate table because it is very large and is stored as JSON.
class Flight(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=100)
class FlightPath(models.Model):
flight = models.OneToOneField(Flight, related_name='flight_path', on_delete=models.CASCADE, blank=True, null=True)
data = models.TextField()
class Section(models.Model):
flight = models.ForeignKey(Flight, related_name='sections', on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=6, default='REPOS')
class Figure(models.Model):
section = models.ForeignKey(Section, related_name='figures', on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=100)
class Aresti(models.Model):
figure = models.ForeignKey(Figure, related_name='aresti', on_delete=models.CASCADE, blank=True, null=True)
code = models.CharField(max_length=20, blank=True, null=True)
In my serialiser, I am overriding the create function as follows:
class APIFlightCreateSerializer(serializers.ModelSerializer):
sections = APISectionSerializer(many=True)
flight_path = APIFlightPathSerializer()
class Meta:
model = Flight
fields = [
'id',
'name',
'sections',
'flight_path'
def create(self, validated_data):
# Override the standard Create method and create a Flight from the validated POST data
# If sent, the Path data is added to the FlightPath table
# First Pop (remove) the Sections and Path data from the validated data
sections_data = validated_data.pop('sections')
flight_path_data = validated_data.pop('flight_path')
# Create a Flight object with just the "header" data
flight = Flight.objects.create(**validated_data)
# Save the Path Data to the FlightPath table
flight_path = FlightPath.objects.create(flight=flight, **flight_path_data)
# Loop through the sections data and add the section objects to the flight
for section_data in sections_data:
# First Pop the figures data from the sections data
figures_data = section_data.pop('figures')
# Create a Section object with just the "header" data
section = Section.objects.create(flight=flight, **section_data)
# Loop through the figures data and add the figure objects to the section
for figure_data in figures_data:
# First Pop the aresti data from the figure data
arestis_data = figure_data.pop('aresti')
# Create a Figure object with just the "header" data
figure = Figure.objects.create(section=section, **figure_data)
# Loop through the aresti data and add the aresti objects to the figure
for aresti_data in arestis_data:
# Create an aresti object
Aresti.objects.create(figure=figure, **aresti_data)
return flight
My Create view consumes the json object:
class APIFlightCreate(generics.CreateAPIView):
queryset = Flight.objects.all()
serializer_class = APIFlightCreateSerializer
def perform_create(self, serializer):
# Called after serializer validation, but before save
auth_user = self.request.user
serializer.save(user = auth_user)
#serializer.save()
def create(self, request, *args, **kwargs):
# Override here for a custom RESPONSE.
# We only need to return the new Flight Id, Unique Code and Name
response = super().create(request, *args, **kwargs)
id = response.data['id']
name = response.data['name']
code = response.data['code']
return Response({'id': id, 'code': code, 'name': name}, status=status.HTTP_201_CREATED).