【问题标题】:Django rest framework serializer with reverse relation具有反向关系的 Django REST 框架序列化程序
【发布时间】:2018-08-31 01:59:45
【问题描述】:

我有两个模型,employeeperson 模型有关系,但 personemployee 模型没有关系。

喜欢:

class Person(models.Model):
    name = models.CharField(max_length=100)
    address = models.CharField(max_length=100)

class Employee(models.Model):
    person = models.ForeignKey(Person, related_name='person_info')
    code = models.CharField()

在这种情况下,我需要个人序列化程序中的 code 字段数据。


我可以通过在人物模型中编写方法或在人物序列化器中使用 SerializerMethodField 来解决这个问题

像这样:

def get_employee_code(self):
    return Employee.objects.get(person=self).id

并将其添加为个人序列化程序中的源

employee_code = serializers.CharField(source='get_employee_code')

或者将员工序列化器添加到人员序列化器中

class PersonSerializer(serializers.ModelSerializer):
    employee = EmployeeSerializer()
    class Meta:
        model = Person
        fields = ('name', 'address', 'employee')

但我试图用反向关系来做到这一点,但我做不到。我试过这样,它给出了一个错误

序列化器:

class PersonSerializer(serializers.ModelSerializer):
    employee_code = serializers.CharField(source='person_info.code')
    class Meta:
        model = Person
        fields = ('name', 'address', 'employee_code')

如何用反向关系解决这个问题?

【问题讨论】:

    标签: python django django-models django-rest-framework django-related-manager


    【解决方案1】:

    目前因为您在 person 属性上使用 ForeignKey 字段,这意味着当您访问反向关系时它会返回一个列表。

    一种解决方案是使用与 slug 相关的字段,尽管这必须将 manyread_only 设置为 True,并且由于 ForeignKey 字段将返回一个列表。

    class PersonSerializer(serializers.ModelSerializer):
        employee_code = serializers.SlugRelatedField(
            source='person_info',
            slug_field='code',
            many=True,
            read_only=True,
        )
    
        class Meta:
            model = Person
            fields = ('name', 'address', 'employee_code')
    

    另一个选项是将您的 ForeignKey 更改为 OneToOneField,这仍需要将 read_only 设置为 True,但它不会返回列表。

    class Person(models.Model):
        name = models.CharField(max_length=100)
        address = models.CharField(max_length=100)
    
    class Employee(models.Model):
        person = models.OneToOneField(Person, related_name='person_info')
        code = models.CharField()
    
    class PersonSerializer(serializers.ModelSerializer):
        employee_code = serializers.SlugRelatedField(
            source='person_info',
            slug_field='code',
            read_only=True,
        )
    
        class Meta:
            model = Person
            fields = ('name', 'address', 'employee_code')
    

    或者,如果您不想更改 ForeignKey,您可以向模型添加 employee_code 属性方法,而不是返回 person_info 关系中的第一个员工代码。

    class Person(models.Model):
        name = models.CharField(max_length=100)
        address = models.CharField(max_length=100)
    
        @property
        def employee_code(self):
            employees = self.person_info.filter()
            if employees.exists():
                return employees.first().code
            return ''
    
    class Employee(models.Model):
        person = models.OneToOneField(Person, related_name='person_info')
        code = models.CharField()
    
    class PersonSerializer(serializers.ModelSerializer):
        employee_code = serializers.CharField(
            read_only=True,
        )
    
        class Meta:
            model = Person
            fields = ('name', 'address', 'employee_code')
    

    【讨论】:

      【解决方案2】:

      您可以通过自定义 SerializerMethodField()

      访问反向关系
      class PersonSerializer(serializers.ModelSerializer):
          employee_code = serializers.SerializerMethodField()
      
          def get_employee_code(self, obj):
              return obj.person_info.code
      
          class Meta:
              model = Person
              fields = ('name', 'address', 'employee_code')
      

      【讨论】:

      • 我已经提到过了。我发现没有方法字段还有其他方法可以做到这一点。
      猜你喜欢
      • 2017-02-09
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 2016-05-19
      • 1970-01-01
      • 2020-12-29
      • 2020-03-24
      • 2013-02-03
      相关资源
      最近更新 更多