【发布时间】:2022-02-04 23:27:29
【问题描述】:
我正在使用 DRF 的 ModelSerializer 和嵌套关系。
问题:
ModelSerializer、ProcedureSerializer 在显示时显示正确定义的所有自定义字段。但是,当将 ProcedureSerializer 嵌套到 customerSerializer 中时,显示的 ProcedureSerializer 的字段只是其模型中定义的那些原始字段,它会丢失自定义的字段。
问题在于,在嵌套模型序列化器中,一些定义在嵌套序列化器上且在列出父序列化器时可见的字段在列出父序列化器时不会显示。
型号:
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
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/,所有必填字段都会显示:
HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"procid": 209,
"timestr": "2022-02-02T17:23:55.048232+05:30",
"template": 1,
"clinic": 21,
"doctor": 4,
"customer": 5596,
"eventtime": "02-02-2022 05:23 PM",
"finding_proc": [
{
"fid": 1423,
"fieldheading": {
"procid": 5,
"name": "Nasal mucosa",
"default": "Nasal mucosa appears normal.",
"sortorder": 1,
"fieldtype": "heading1",
"template": 1
},
"value": "",
"linkedprocedure": {
"procid": 209,
"timestr": "2022-02-02T17:23:55.048232+05:30",
"template": 1,
"clinic": 21,
"doctor": 4,
"customer": 5596
}
},
{
"fid": 1424,
"fieldheading": {
"procid": 6,
"name": "Turbinates",
"default": "Bilateral inferior, middle and superior turbinates appear normal.",
"sortorder": 15,
"fieldtype": "heading1",
"template": 1
},
"value": "Left MT bulky, suggestive of concha bullosa",
"linkedprocedure": {
"procid": 209,
"timestr": "2022-02-02T17:23:55.048232+05:30",
"template": 1,
"clinic": 21,
"doctor": 4,
"customer": 5596
}
},
{
"fid": 1425,
"fieldheading": {
"procid": 7,
"name": "Septum",
"default": "No significant nasal septal deviation.",
"sortorder": 5,
"fieldtype": "heading1",
"template": 1
},
"value": "",
"linkedprocedure": {
"procid": 209,
"timestr": "2022-02-02T17:23:55.048232+05:30",
"template": 1,
"clinic": 21,
"doctor": 4,
"customer": 5596
}
},
{
"fid": 1426,
"fieldheading": {
"procid": 8,
"name": "Middle meatus",
"default": "Bilateral middle meatus normal. No discharge, or polyps.",
"sortorder": 50,
"fieldtype": "heading1",
"template": 1
},
"value": "",
"linkedprocedure": {
"procid": 209,
"timestr": "2022-02-02T17:23:55.048232+05:30",
"template": 1,
"clinic": 21,
"doctor": 4,
"customer": 5596
}
},
{
"fid": 1427,
"fieldheading": {
"procid": 9,
"name": "Inferior Meatus",
"default": "Inferior Meatus is normal. Opening of Hasner's valve normal.",
"sortorder": 30,
"fieldtype": "heading1",
"template": 1
},
"value": "Nasopharynx shows adenoid enlargement, occupying less than 2/3rd of the posterior choana.",
"linkedprocedure": {
"procid": 209,
"timestr": "2022-02-02T17:23:55.048232+05:30",
"template": 1,
"clinic": 21,
"doctor": 4,
"customer": 5596
}
},
{
"fid": 1428,
"fieldheading": {
"procid": 10,
"name": "Sphenoethmoidal recess",
"default": "Bilateral sphenoethmoidal recesses normal",
"sortorder": 60,
"fieldtype": "heading1",
"template": 1
},
"value": "",
"linkedprocedure": {
"procid": 209,
"timestr": "2022-02-02T17:23:55.048232+05:30",
"template": 1,
"clinic": 21,
"doctor": 4,
"customer": 5596
}
},
{
"fid": 1429,
"fieldheading": {
"procid": 11,
"name": "Final Impression",
"default": "Nasal endoscopy normal",
"sortorder": 1000,
"fieldtype": "heading1",
"template": 1
},
"value": "Adenoid hypertrophy noted",
"linkedprocedure": {
"procid": 209,
"timestr": "2022-02-02T17:23:55.048232+05:30",
"template": 1,
"clinic": 21,
"doctor": 4,
"customer": 5596
}
}
]
}
但是,如果我尝试查看嵌套 ProcedureSerializer 的序列化器 customerSerializer,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(它实际上是一个模型方法)和 find_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())"
这里发生了什么?如何获取嵌套父序列化程序中的所有字段?
【问题讨论】:
标签: python django serialization django-rest-framework