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)