【问题标题】:When a ModelSerializer is nested, it loses its custom defined fields嵌套 ModelSerializer 时,它会丢失其自定义字段
【发布时间】: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


    【解决方案1】:

    出现问题是因为我在 Meta 类中而不是在主类中包含了对嵌套序列化程序的引用。 @Smixi at 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 = []
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-07
      • 1970-01-01
      • 2013-01-13
      相关资源
      最近更新 更多