首页 > 解决方案 > Django Rest 框架:带序列化器的 ForeignKey

问题描述

我有两个简单的表,带有一个外键。我想用外键检索表中的数据:

CREATE TABLE `firerisk_reminder` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` longtext NOT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `firerisk_remindertype` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  `reminder_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`),
  KEY `firerisk_remindertyp_reminder_id_03340ffc_fk_firerisk_` (`reminder_id`),
  CONSTRAINT `firerisk_remindertyp_reminder_id_03340ffc_fk_firerisk_` FOREIGN KEY (`reminder_id`) REFERENCES `firerisk_reminder` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

而且,我在 django 中的模型:

class Reminder(models.Model):
    name = models.TextField(default='')
    report = models.OneToOneField(Report, related_name='reminder', on_delete=models.PROTECT)

    def __str__(self):
        return self.name

class ReminderType(models.Model):
    name = models.CharField(max_length=45, unique=True)
    reminder = models.ForeignKey(Reminder,related_name='reminderstype',on_delete=models.PROTECT)

在 DRF 中,我使用这样的序列化程序:

class ReminderTypeSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField()

    class Meta:
        model = ReminderType
        fields = ('id', 'name')
        ordering = ('name',)

class ReminderSerializer(serializers.ModelSerializer):
    remindertypes = ReminderTypeSerializer(read_only=True)
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField()

    class Meta:
        model = Reminder
        ordering = ('name',)
        fields = ('id', 'name', 'remindertypes')

最后,我的 ViewSets :

class ReminderTypeViewSet(viewsets.ModelViewSet):
    serializer_class = ReminderTypeSerializer
    queryset = ReminderType.objects.all().order_by('name')
    # Authentification !
    permission_classes = (IsAuthenticated,)
    # Only 'get' method
    http_method_names = ['get']

class ReminderViewSet(viewsets.ModelViewSet):
    serializer_class = ReminderSerializer
    queryset = Reminder.objects.all().order_by('name')
    # Authentification !
    permission_classes = (IsAuthenticated,)
    # Only 'get' method
    http_method_names = ['get']

当我反转对序列化程序的调用时,如下所示:

class ReminderTypeSerializer(serializers.ModelSerializer):
    reminder = ReminderSerializer(read_only=True)
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField()

我有数据,但关系对我没有意义(提醒类型):

[
    {
        "id": 1,
        "name": "yyyyyyyy",
        "reminder": {
            "id": 1,
            "name": "First report test"
        }
    },
    {
        "id": 2,
        "name": "xxxxxxxx",
        "reminder": {
            "id": 1,
            "name": "First report test"
        }
    }
]

我已经测试了其他一些关系(嵌套、相关等),但没有成功。

你能帮我吗 ?谢谢 F。

标签: djangorestdjango-rest-framework

解决方案


您已经设置related_name='reminderstype'了提醒字段,因此它应该reminderstype = ReminderTypeSerializer(read_only=True, many=True)在序列化程序中。

class ReminderSerializer(serializers.ModelSerializer):
    reminderstype = ReminderTypeSerializer(read_only=True, many=True)
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField()

    class Meta:
        model = Reminder
        ordering = ('name',)
        fields = ('id', 'name', 'reminderstype')

或者remindertypes = ReminderTypeSerializer(read_only=True, source='reminderstype')

class ReminderSerializer(serializers.ModelSerializer):
    remindertypes = ReminderTypeSerializer(read_only=True, source='reminderstype', many=True)

related_name如果您需要获取所有相关的提醒类型,您应该在序列化程序中使用ReminderSerializer.

注意添加many=True以序列化对象列表。


推荐阅读