Double nested serializer structure and generated ids

Hello,

(The data in the samples are changed to protect the innocent)

  • This is with Django 3.1.7

I have double nested serializers as follows:

job (parent)
job_resource (child)
jr_p (grandchild)
jr_s (grandchild)
jr_c (grandchild)

When running a query with a json similar to this:
{“other_data” : “data”, “job_resource”: [{“other_data”: 0, “JRC”: {“other_data”: “my_data”}}, {“other_data”: 1, “JRC”: {“data”: “mydata”}}]}

I am getting a failure that “job_resource”: [{“job”: [“This field is required.”]},…
“job” in this case (I believe) is the foreign key inside of JobResource.

My expectation was that since I am creating the job, job_resources, and grandchildren at the same time, that django would populate the foreign key id when it creates the job in the db. I cannot know what the job id will be until the job is created.
Clearly, I am doing something incorrectly and was hoping an expert here might be able to share their knowledge with me.

models

class Job(models.Model):
    suite = models.ForeignKey(Suite, related_name="job", on_delete=models.CASCADE)
    other_fields
    

    class Meta:
        unique_together = (("id_in_suite", "suite"),)

    def suite_link(self):
        link_url = "/admin/results_manager/suite/?id={}".format(self.suite.id)
        link_text = str(self.suite)
        return format_html('<a href="{}">{}</a>', link_url, link_text)

    suite_link.short_description = "Suite"

    def done_spark_cases_link(self):
        num_of_spark_tasks = SparkTask.objects.filter(Q(job=self)).count()
        sparktask_by_job_url = f"/admin/results_manager/sparktask/?job__id={self.id}"
        link_text = f"Spark cases (Count: {num_of_spark_tasks})"
        return format_html('<a href="{}">{}</a>', sparktask_by_job_url, link_text)

    done_spark_cases_link.short_description = "Done Spark cases"

    objects = DataFrameManager()


class JobResource(models.Model):
    job = models.ForeignKey(Job, related_name="job_resources", on_delete=models.CASCADE)
    other_fields 
    
	
class JRP(models.Model):
    job_resource = models.OneToOneField(JobResource, related_name="jrp", on_delete=models.CASCADE, null=True, blank=True)
    other_fields
	
class JRC(models.Model):
    job_resource = models.OneToOneField(JobResource, related_name="jrc", on_delete=models.CASCADE, null=True, blank=True)  
	other_fields
	
class JRS(models.Model):
    job_resource = models.OneToOneField(JobResource, related_name="jrs", on_delete=models.CASCADE, null=True, blank=True)
    other_fields
	
	
serilzers

class JRPSerializer(serializers.ModelSerializer):
    class Meta:
        fields = '__all__'
        model = models.JRP

class JRCSerializer(serializers.ModelSerializer):
    class Meta:
        fields = '__all__'
        model = models.JRC

class JRSSerializer(serializers.ModelSerializer):
    class Meta:
        fields = '__all__'
        model = models.JRS

class JobResourceSerializer(serializers.ModelSerializer):

    JRP = JRPSerializer(required=False, allow_null=True)
    JRS = JRSSerializer(required=False, allow_null=True)
    JRC = JRCSerializer(required=False, allow_null=True)
    class Meta:
        fields = '__all__'
        model = models.JobResource

    def create(self, validated_data):
        jrp_data = validated_data.pop('JRP')
        jrs_data = validated_data.pop('JRS')
        jrc_data = validated_data.pop('JRC')

        job_resource = JobResource.objects.create(**validated_data)

        for p_data in jrp_data:
            JRP.objects.update_or_create(job_resource=job_resource, **p_data)

        for s_data in jrc_data:
            JRS.objects.update_or_create(job_resource=job_resource, **s_data)

        for c_data in jrc_data:
            JRC.objects.update_or_create(job_resource=job_resource, **c_data)

        return job_resource

class JobSerializer(serializers.ModelSerializer):
    
    job_resource = JobResourceSerializer(many=True) 
    class Meta:
        fields = '__all__'
        model = models.Job

    def create(self, validated_data):
        job_resource_data = validated_data.pop('JobResources')
        job = Job.objects.create(**validated_data)

        for jr_data in job_resource_data:
            job_resource = JobResource.objects.create(job=job, **jr_data)
            jrc_data = jr_data.pop('JRC')
            jrs_data = jr_data.pop('JRS')
            jrp_data = jr_data.pop('JRP')

            for c_data in jrc_data:
                JRC.objects.update_or_create(job_resource=job_resource, **c_data)

            for s_data in jrs_data:
                JRS.objects.update_or_create(job_resource=job_resource, **s_data)
            
            for p_data in jrp_data:
                JRP.objects.update_or_create(job_resource=job_resource, **p_data)