使用 django-rest-framework 序列化器检索外键值
- 2025-03-11 08:54:00
- admin 原创
- 66
问题描述:
我正在使用 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'}]
我已阅读了有关 REST 框架的反向关系的文档,但结果似乎与非反向字段相同。我是否遗漏了某些显而易见的东西?
解决方案 1:
在 DRF 版本 3.6.3 中,这对我有用
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.CharField(source='category.name')
class Meta:
model = Item
fields = ('id', 'name', 'category_name')
更多信息可以在这里找到:序列化器字段核心参数
解决方案 2:
只需使用相关字段,无需设置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')
解决方案 3:
您可以做的另一件事是:
在模型中创建一个
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
解决方案 4:
这对我来说很好:
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.ReadOnlyField(source='category.name')
class Meta:
model = Item
fields = "__all__"
解决方案 5:
简单的解决方案,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__"
解决方案 6:
工作于 2018 年 8 月 8 日,使用 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。然后我们需要在 Meta 上read_only_fields
声明该字段(最好明确一点,正如咒语所说:python 之禅)。foreign
`fields`
解决方案 7:
此解决方案更好,因为无需定义源模型。但序列化器字段的名称应与外键字段名称相同
class ItemSerializer(serializers.ModelSerializer):
category = serializers.SlugRelatedField(read_only=True, slug_field='title')
class Meta:
model = Item
fields = ('id', 'name', 'category')
解决方案 8:
对于那些想要替换ForeignKey 字段(显示 ID)的人,您仍然可以使用方便__all__
的语法,并根据需要简单地覆盖字段名称。例如:
class MyModelSerializer(serializers.ModelSerializer):
# override the category field that would otherwise show an integer value
# for the ID with the field of that model you choose. "name" here.
category = serializers.ReadOnlyField(source='category.name')
class Meta:
model = MyModel
fields = '__all__'
在我看来,这很方便,因为您__all__
以后仍然可以使用该语法来捕获任何添加的字段。任何被覆盖的操作都是手动完成的,如果需要恢复,可以手动完成一些操作而无需更改任何其他语法。
扫码咨询,免费领取项目管理大礼包!