125

我正在使用 django rest 框架来创建 API。我有以下型号:

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

    def __unicode__(self):
        return self.name


class Item(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, related_name='items')

    def __unicode__(self):
        return self.name

要为我要做的类别创建一个序列化程序:

class CategorySerializer(serializers.ModelSerializer):
    items = serializers.RelatedField(many=True)

    class Meta:
        model = Category

...这将为我提供:

[{'items': [u'Item 1', u'Item 2', u'Item 3'], u'id': 1, 'name': u'Cat 1'},
 {'items': [u'Item 4', u'Item 5', u'Item 6'], u'id': 2, 'name': u'Cat 2'},
 {'items': [u'Item 7', u'Item 8', u'Item 9'], u'id': 3, 'name': u'Cat 3'}]

我将如何从 Item 序列化程序中获得相反的结果,即:

[{u'id': 1, 'name': 'Item 1', 'category_name': u'Cat 1'},
{u'id': 2, 'name': 'Item 2', 'category_name': u'Cat 1'},
{u'id': 3, 'name': 'Item 3', 'category_name': u'Cat 1'},
{u'id': 4, 'name': 'Item 4', 'category_name': u'Cat 2'},
{u'id': 5, 'name': 'Item 5', 'category_name': u'Cat 2'},
{u'id': 6, 'name': 'Item 6', 'category_name': u'Cat 2'},
{u'id': 7, 'name': 'Item 7', 'category_name': u'Cat 3'},
{u'id': 8, 'name': 'Item 8', 'category_name': u'Cat 3'},
{u'id': 9, 'name': 'Item 9', 'category_name': u'Cat 3'}]

我已经阅读了有关其余框架的反向关系的文档,但这似乎与非反向字段的结果相同。我错过了一些明显的东西吗?

4

7 回答 7

126

在 DRF 3.6.3 版中,这对我有用

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.CharField(source='category.name')

    class Meta:
        model = Item
        fields = ('id', 'name', 'category_name')

更多信息可以在这里找到:序列化器字段核心参数

于 2017-06-13T20:08:10.433 回答
108

只需使用相关字段而不设置many=True.

请注意,还因为您希望输出名为category_name,但实际字段为category,您需要source在序列化器字段上使用参数。

以下应该为您提供所需的输出...

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.RelatedField(source='category', read_only=True)

    class Meta:
        model = Item
        fields = ('id', 'name', 'category_name')
于 2013-06-25T08:56:19.677 回答
36

您可以做的另一件事是:

  • Item在您的模型中创建一个返回类别名称的属性和
  • 将其公开为ReadOnlyField.

你的模型看起来像这样。

class Item(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, related_name='items')

    def __unicode__(self):
        return self.name

    @property
    def category_name(self):
        return self.category.name

你的序列化器看起来像这样。请注意,序列化程序将category_name通过命名具有相同名称的字段来自动获取模型属性的值。

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.ReadOnlyField()

    class Meta:
        model = Item
于 2016-09-09T07:07:55.203 回答
23

这对我来说很好:

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.ReadOnlyField(source='category.name')
    class Meta:
        model = Item
        fields = "__all__"
于 2018-08-06T08:53:14.160 回答
10

source='category.name'category键及其.name属性的简单解决方案 。

from rest_framework.serializers import ModelSerializer, ReadOnlyField
from my_app.models import Item

class ItemSerializer(ModelSerializer):
    category_name = ReadOnlyField(source='category.name')

    class Meta:
        model = Item
        fields = "__all__"
于 2018-12-13T20:09:28.247 回答
9

工作于 08/08/2018 和 DRF 版本 3.8.2:

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.ReadOnlyField(source='category.name')

    class Meta:
        model = Item
        read_only_fields = ('id', 'category_name')
        fields = ('id', 'category_name', 'name',)

使用 Metaread_only_fields我们可以准确地声明哪些字段应该是只读的。然后我们需要foreign在 Meta 上声明该字段fields(最好是明确的口头禅:python 的禅宗)。

于 2018-08-08T11:40:51.757 回答
2

此解决方案更好,因为无需定义源模型。但是序列化器字段的名称应该与外键字段名称相同

class ItemSerializer(serializers.ModelSerializer):
    category = serializers.SlugRelatedField(read_only=True, slug_field='title')

    class Meta:
        model = Item
        fields = ('id', 'name', 'category')
于 2020-09-07T09:58:40.953 回答