Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用django rest框架序列化程序检索外键值_Python_Django_Django Rest Framework - Fatal编程技术网

Python 使用django rest框架序列化程序检索外键值

Python 使用django rest框架序列化程序检索外键值,python,django,django-rest-framework,Python,Django,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 = m

我正在使用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框架的文档,但这似乎与非反向字段的结果相同。我是否遗漏了一些明显的内容?

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

请注意,由于您希望输出名为
category\u 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')

您可以做的另一件事是:

  • 项目
    模型中创建一个属性,返回类别名称和
  • 将其公开为
    只读字段
你的模型应该是这样的

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\u name
model属性的值

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

更多信息可以在这里找到:

这对我来说很好:

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

于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
只读字段
我们可以准确地声明哪些字段应该是只读的。然后,我们需要在Meta
字段
上声明
外来
字段(最好像咒语那样明确:)。

简单解决方案
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__"

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

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

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

检索类别模型的所有字段怎么样?如果要检索类别模型的所有字段,请创建类别序列化程序,并将其保存在类似category_name=categoryserlizer()的代码中,我尝试过这样做,但遇到一个错误
关系字段必须提供“queryset”参数,或者设置read_only='True'
,或者如果希望支持创建/更新,则提供queryset属性,例如:
category\u name=serializers.RelatedField(source='category',queryset=category.objects.all())
我想是吧。如果您得到
断言错误:…
请使用此答案,但您必须小心,因为如果项目模型中的“类别”字段设置为blank=True,则会引发非类型错误