使用 django-rest-Framework 序列化器检索外键值

我使用 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'}]

如何从项序列化程序获得相反的结果? 例如:

[{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'}]

我已经通读了关于 rest 框架的 反向关系文档,但结果似乎与非反向字段相同。我漏掉了什么明显的东西吗?

196678 次浏览

只需使用一个相关的字段,而不需要设置 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')

你可以做的另一件事是:

  • 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

在 DRF 3.6.3版本中,这对我很有用

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


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

更多信息可以在这里找到: Serializer Fields 核心参数

这对我很有效:

class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.ReadOnlyField(source='category.name')
class Meta:
model = Item
fields = "__all__"

在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',)

使用 Meta read_only_fields,我们可以精确地声明哪些字段应该是 read _ only。然后,我们需要在 Meta fields上声明 foreign字段(最好像咒语所说的那样明确: 蟒蛇禅)。

简单的解决办法 其中 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__"

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

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


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