如何在JSON中获取PrimaryKeyRelatedField的字符串表示形式

3

我正在使用Django REST框架,对此还比较新手。

我希望在我的JSON输出中,对于manytomanyfield和foreignkey字段,能够有字符串表示而非值。

models.py

class Movie(models.Model):
    """Movie objects"""
    name = models.CharField(max_length=128)
    directorName = models.ForeignKey(Director)
    genre = models.ManyToManyField(Genre)

serializers.py

class MovieSerializer(serializers.ModelSerializer):
    """
    Serialiazing all the Movies.
    """
    genre = serializers.PrimaryKeyRelatedField(many=True, queryset=Genre.objects.all())
    directorName = serializers.PrimaryKeyRelatedField(queryset=Director.objects.all())
    owner = serializers.ReadOnlyField(source='owner.username')
    class Meta:
        model = Movie
        fields = ('popularity',"directorName",'genre','imdbScore','name','owner')

JSON输出

{"popularity":"90.0","directorName":1,"genre":[1,2,3],"imdbScore":"8.9","name":"Titanic"}

我只得到了directorName和genre的值,而不是它们的display_name。

请建议如何纠正这个问题。

编辑 [已解决] 您需要重写PrimaryKeyRelatedField的to_representation()方法,因为它返回pk。

2个回答

7
为了实现这一点,您需要重写PrimaryKeyRelatedFieldto_representation()方法,因为它返回pk。您可以创建一个继承自PrimaryKeyRelatedFieldMyPrimaryKeyRelatedField,然后覆盖其to_representation()方法。相比于PrimaryKeyRelatedField返回的value.pk,现在返回字符串表示形式。我使用six.text_type()代替str()来处理Python 2(unicode)和Python 3(str)版本的情况。
from django.utils import six
from rest_framework import serializers

class MyPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):

    def to_representation(self, value):
        return six.text_type(value) # returns the string(Python3)/ unicode(Python2) representation now instead of pk 

您的serializers.py文件应该如下所示:
class MovieSerializer(serializers.ModelSerializer):
    """
    Serialiazing all the Movies.
    """
    genre = MyPrimaryKeyRelatedField(many=True, queryset=Genre.objects.all())
    directorName = MyPrimaryKeyRelatedField(queryset=Director.objects.all())
    owner = serializers.ReadOnlyField(source='owner.username')
    class Meta:
        model = Movie
        fields = ('popularity',"directorName",'genre','imdbScore','name','owner')

2
问题已解决,其实我在 directorName 上设置了 many=True,这就是为什么它给我返回了 'Director' object is not iterable 错误。但现在,我得到的是 directorName 的字符串表示之外的内容 - "directorName": "<rest_framework.relations.PKOnlyObject object at 0x7f40ac40ca50>" - Rohan
你需要在你的Director模型上添加一个__str__方法。然后它应该正常工作。 - Rahul Gupta
好的。我已经将str(value)更改为six.text_type(value)。现在它应该能够同时处理Python2和Python3版本了。 - Rahul Gupta
在你的__unicode__方法中,尝试这样写:return u'%s' % (self.name) - Rahul Gupta
2
我在to_representation(self, value)方法中得到了相同的rest_framework.relations.PKOnlyObject对象作为值。我的解决方案是在我的自定义PrimaryKeyRelatedField中重写use_pk_only_optimization方法,将其返回False,因为这个方法 - Aylen
显示剩余8条评论

3
最简单的方法可能是使用StringRelatedField
class MovieSerializer(serializers.ModelSerializer):
    directorName = serializers.StringRelatedField(many=True)

class Director(Model):
    # [...]
    def __unicode__(self):
        return self.directorName

然而,当您需要不同表示 Director 模型时,上述方法行不通。在这种情况下,您需要使用自定义序列化程序(请参见 Rahul Gupta 的答案)。

但是它给我返回了这个错误:'关系字段不应该提供一个queryset参数,' - Rohan
那是我犯的一个复制粘贴错误,StringRelatedField 不需要/接受一个 queryset。 - dhke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接