Отсутствующие поля вложенного сериализатора
Я использую DRF's ModelSerializer и вложенные отношения. Проблема заключается в том, что во вложенном сериализаторе моделей некоторые поля, определенные и видимые при листинге вложенного сериализатора, не отображаются при листинге родительского.
Модели:
class customer(models.Model):
cstid = models.AutoField(primary_key=True, unique=True)
name = models.CharField(max_length=35, blank=False)
...SNIPPED
class Meta:
unique_together = ["name", "mobile", "linkedclinic"]
ordering = ['name']
def __str__(self):
return self.name
class Procedure(models.Model):
procid = models.AutoField(primary_key=True, unique=True)
timestr = models.DateTimeField(default=timezone.now)
template = models.ForeignKey(
ProcedureTemplate, on_delete=models.CASCADE, blank=True, null=True)
clinic = models.ForeignKey(Clinic, on_delete=models.CASCADE)
doctor = models.ForeignKey(
doctor, on_delete=models.SET_NULL, blank=True, null=True)
customer = models.ForeignKey(
customer, on_delete=models.CASCADE, null=False, related_name='procedures')
def __str__(self):
return f'{self.template} for {self.customer} on {self.timestr}'
def eventtime(self):
class_date = timezone.localtime(self.timestr)
return class_date.strftime("%d-%m-%Y %I:%M %p")
Сериализаторы:
class FindingSerializer(serializers.ModelSerializer):
class Meta:
model = Finding
depth = 1
fields = [
'fid',
'fieldheading',
'value',
'linkedprocedure',
]
class ProcedureSerializer(serializers.ModelSerializer):
finding_proc = FindingSerializer(many=True, read_only=True)
class Meta:
model = Procedure
depth = 2
fields = [
'procid',
'timestr',
'template',
'clinic',
'doctor',
'customer',
'eventtime',
'finding_proc',
]
class customerSerializer(ConvertNoneToStringSerializerMixin, serializers.ModelSerializer):
def get_unique_together_validators(self):
"""Overriding method to disable unique together checks"""
return []
class Meta:
model = customer
depth = 3
biovar_data = Biovariable_dataSerializer(
read_only=True, many=True) # many=True is required
procedures = ProcedureSerializer(
read_only=True, many=True) # many=True is required
# allergies = allergiesSerializer(
# read_only=True, many=True) # many=True is required
fields = [
'cstid',
'date_of_registration',
'insurance_number',
'name',
'age',
'ageyrs',
'agemnths',
'dob',
'gender',
'maritalstatus',
'mobile',
'alternate',
'email',
'address',
'city',
'occupation',
'bloodgroup',
'linkedclinic',
'allergies_data',
'biovar_data',
'procedures'
]
validators = []
none_to_str_fields = ('insurance_number', )
Если я отображаю экземпляр процедуры: GET /api/procedures/209/, все необходимые поля отображаются:
Но если я попытаюсь просмотреть сериализатор customerSerializer, который вложен в ProcedureSerializer, все поля ProcedureSerializer не отображаются:
`GET /api/customer/5596/`
{
"cstid": 5596,
"name": "Some name",
"age": "10yr",
"ageyrs": 9,
SNIPPED
"linkedclinic": {},
"procedures": [
{
"procid": 209,
"timestr": "2022-02-02T17:23:55.048232+05:30",
"template": {
"templid": 1,
"title": "DNE",
"description": "Diagnostic Nasal Endoscopy",
"clinic": {
"clinicid": 10,
"SNIP
}
},
"clinic": {
"clinicid": 21,
SNIP
},
"doctor": {
"docid": 4,
SNIP
},
"customer": {
"cstid": 5596,
"date_of_registration": "2021-12-25",
SNIP
}
}
}
]
}
Так, отмечается, что два из тех полей, которые есть в ProcedureSerializer, включая eventtime (который на самом деле является методом модели) и finding_proc (который является вложенным сериализатором), отсутствуют в ProcedureSerializer.
repr(ProcedureSerializer()) gives:
"ProcedureSerializer():\n procid = IntegerField(read_only=True)\n timestr = DateTimeField(required=False)\n template = PrimaryKeyRelatedField(allow_null=True, queryset=ProcedureTemplate.objects.all(), required=False)\n clinic = PrimaryKeyRelatedField(queryset=Clinic.objects.all())\n doctor = PrimaryKeyRelatedField(allow_null=True, queryset=doctor.objects.all(), required=False)\n customer = PrimaryKeyRelatedField(queryset=customer.objects.all())\n eventtime = ReadOnlyField()\n finding_proc = FindingSerializer(many=True, read_only=True):\n fid = IntegerField(read_only=True)\n fieldheading = NestedSerializer(read_only=True):\n procid = IntegerField(read_only=True)\n name = CharField(max_length=200)\n default = CharField(max_length=1000)\n sortorder = IntegerField(max_value=2147483647, min_value=-2147483648, required=False)\n fieldtype = ChoiceField(choices=(('heading1', 'Heading1'), ('heading2', 'Heading2')), required=False)\n template = PrimaryKeyRelatedField(queryset=ProcedureTemplate.objects.all())\n value = CharField(allow_blank=True, max_length=5000, required=False)\n linkedprocedure = NestedSerializer(read_only=True):\n procid = IntegerField(read_only=True)\n timestr = DateTimeField(required=False)\n template = PrimaryKeyRelatedField(allow_null=True, queryset=ProcedureTemplate.objects.all(), required=False)\n clinic = PrimaryKeyRelatedField(queryset=Clinic.objects.all())\n doctor = PrimaryKeyRelatedField(allow_null=True, queryset=doctor.objects.all(), required=False)\n customer = PrimaryKeyRelatedField(queryset=customer.objects.all())"
Что здесь происходит? Как я могу получить все поля во вложенном родительском сериализаторе?
Проблема возникла из-за того, что я включил ссылку на вложенный сериализатор в класс Meta, а не в основной класс. На проблему указал @Smixi на Github (Все заслуги принадлежат ему. Я публикую ответ, чтобы он мог помочь другим людям, которые могут совершить ту же ошибку, что и я)
Правильным кодом будет:
class customerSerializer(ConvertNoneToStringSerializerMixin, serializers.ModelSerializer):
procedures = ProcedureSerializer(
read_only=True, many=True) # many=True is required
biovar_data = Biovariable_dataSerializer(
read_only=True, many=True) # many=True is required
def get_unique_together_validators(self):
"""Overriding method to disable unique together checks"""
return []
class Meta:
model = customer
depth = 3
fields = [
'cstid',
'date_of_registration',
'insurance_number',
'name',
'age',
'ageyrs',
'agemnths',
'dob',
'gender',
'maritalstatus',
'mobile',
'alternate',
'email',
'address',
'city',
'occupation',
'bloodgroup',
'linkedclinic',
'allergies_data',
'biovar_data',
'procedures'
]
validators = []