使用ChoiceField时出现“类型错误对象不可JSON序列化”的问题

5

我将使用Django Rest框架创建一个REST API,不能使用任何其他库或插件。过去几天中,我一直存在一个问题,而且我很难解决。

在我的serializer.py文件中,我有以下代码:

class BookSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.ReadOnlyField(source = 'owner.username')
    genres = serializers.ChoiceField(choices=Genre.objects.values_list())
    # genres = GenreSerializer()

class Meta:
    model = VideoGame
    fields = ('title', 'description', 'brief', 'genres', 'owner') 

我希望当用户访问GUI并尝试创建新书时,他们可以从一个ChoiceField中选择流派,然后将其翻译为其ID。如果用户通过rest API访问,则必须输入ID。
当数据库为空时,我能够成功将新书发布到服务器并使用ChoiceField选择下拉菜单。但是当数据库有条目时,我会收到以下错误。当我使用序列化程序替换ChoiceField时,这个问题得到了解决。但是,我只留下一个输入字段而不是ChoiceField。有人知道如何解决这个问题吗?
TypeError at /book/
<Genre: Genre object> is not JSON serializable
2个回答

2
你需要关注以下两点:a) ChoiceField 需要接收什么样的选项,b) values_list() 返回什么。
a) 根据文档ChoiceField 需要传入一个有效值列表或者是 (key, display_name) 元组列表。在这个例子中,有效值应该是你的 Genres 的主键 id。
b) 根据文档,不带参数的 values_list() 返回模型中所有字段按照声明顺序排列的结果。
我不认为你会从使用 choices=Genre.objects.values_list() 得到你在问题中展示的错误信息...也许你是尝试使用了 choices=Genre.objects.all()
无论如何,你可以这样做:
class BookSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.ReadOnlyField(source = 'owner.username')
    genres = serializers.ChoiceField(choices=Genre.objects.values_list('pk', flat=True))

如果你的Genre模型中有一个字段可以作为“显示名称”,那么你可以这样做:
class BookSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.ReadOnlyField(source = 'owner.username')
    genres = serializers.ChoiceField(choices=Genre.objects.values_list('pk', 'name'))

然而,以上两种选项存在一个问题,那就是查询集会在导入包含资源的文件时被评估(因为ChoiceField立即将其转换为列表) 有这样的副作用在导入时是不好的做法。此外,每次启动服务器时只能评估一次,当您更改类别时,选择将过时。幸运的是,还有一种更好的选择:
http://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield。 这类似于Django中的ModelChoiceField。它具有“queryset”参数,用于验证选择...但与ChoiceField不同,它知道不要立即评估查询集。每次需要验证选择时,它将被评估。 所以你应该这样做:
class BookSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.ReadOnlyField(source = 'owner.username')
    genres = serializers.PrimaryKeyRelatedField(queryset=Genre.objects.all())

如果需要为关系字段上的选项自定义“显示名称”,您可以参考这里的文档


1
我想使用ChoiceField,因为它会自动在OPTIONS调用中添加可用选项。我尝试了这种方式,使用PrimaryKeyRelatedField,但它不会在OPTIONS中返回可用选项,而使用ChoiceField时,我遇到了与@Oonah相同的问题。我的代码:activity_type = serializers.ChoiceField( choices=ActivityType.objects.filter( primary_activity=True).values_list("id", "name") ) - Karina Klinkevičiūtė

0

通常我会在模型更改但未迁移时收到这样的错误提示。尝试进行迁移可能会有所帮助。


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