Slow save and update of child/grandchild data

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:

|- 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 = [
    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 = auth_user)
    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 =['id']
        name =['name']
        code =['code']
        return Response({'id': id, 'code': code, 'name': name}, status=status.HTTP_201_CREATED).


If am well understand your problem, here is what you can do.
You can use the power of related_name attribute in your relationships that you will fetch parent once and you get all data and you wont need to query again for childres or grandchildrens. Example with Flight you can update FlightPath without looping since its one-to-one like this

flight = Flight.objects.filter(pk=given_pk).first()
path = flight.flight_path.first()
if path: = YourNewData

And for the case of childres of flight_path you can use the same approach from the results above

sections = flight.sections.first()
if sections:
    ## Since sections is not one to one related, you will need to loop.
    all_sections = sections.figures.all()
    for section in all_sections:
       ## If your looking for specific section you can just filter it here = YourNewSectionName

This is very long approach in case you update specific data for childres but if your updating by providing all new data, you can simply delete childrens the create again.

## Since your using on_delete=models.CASCADE it will delete upto grandchildrens