python - JSONField 对于 POST 序列化为 json,对于 GET 序列化为字符串

标签 python json django django-models django-rest-framework

我的代码可能存在一个非常简单的问题,但几天来我一直在努力解决这个问题,但没有取得任何进展。

重要包裹:

Django==1.11.3
django-cors-headers==2.1.0
djangorestframework==3.7.0
drf-nested-routers==0.90.0
psycopg2==2.7.3
pycparser==2.18

这是正在发生的事情:

我通过 AJAX 调用创建模型

enter image description here

我的服务器正确地将 brainstorm_data 字段序列化为 json 对象。

现在我将我的用户导航到下一页并获取当前模型

enter image description here

出于某种原因,brainstorm_data 现在作为字符串返回。每当我对此资源调用 GET 请求时,我总是会得到 JSON 对象的字符串表示形式。

相关代码如下:

模型.py

from django.contrib.postgres.fields import JSONField

class Adventure(TimeStampedModel,
                    models.Model):
        name = models.CharField(max_length=200)
        user = models.ForeignKey(User)
        world = models.ForeignKey(World)
        theme = models.ForeignKey(Theme, default=1)
        brainstorm_data = JSONField()
        image_src = models.CharField(max_length=400, null=True, blank=True)
        sentence_summary = models.TextField(null=True, blank=True)
        paragraph_summary = models.TextField(null=True, blank=True)
        page_summary = models.TextField(null=True, blank=True)
        outline_complete = models.BooleanField(default=False)
        brainstorm_complete = models.BooleanField(default=False)
        private = models.BooleanField(default=False)

        def __str__(self):
            return self.name

views.py

class MyAdventuresViewSet(viewsets.ModelViewSet):
    queryset = Adventure.objects.all()
    serializer_class = AdventureSerializer
    permission_classes = (permissions.IsAuthenticated,)

    def get_queryset(self):
        return Adventure.objects.filter(user=self.request.user)

    def create(self, request, *args, **kwargs):
        user = self.request.user
        world = World.objects.filter(user=user).first()

        if not world:
            world = World.objects.create(name='My World', user=user,
                                         description="This is a default world we created for your adventures",
                                         image_src=static('worlds/images/world_placeholder.png'))

        data = request.data.copy()
        data['user'] = user.pk
        data['world'] = world.pk
        data['theme'] = 1  # default theme
        data['brainstorm_data'] = default_brainstorm
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        adventure = serializer.save()

        Storyboard.objects.create(adventure=adventure, raw=default_storyboard['raw'], html=default_storyboard['html'])

        return JsonResponse(serializer.data)

    @detail_route(methods=['post'])
    def complete_outline(self, request, pk):
        adventure = Adventure.objects.get(pk=self.kwargs['pk'])
        complete_adventure_outline(adventure)

        serializer = self.get_serializer(data=adventure)
        serializer.is_valid(raise_exception=True)
        return JsonResponse(serializer.data, status=200)

    @detail_route(methods=['post'])
    def genres(self, request, pk):
        genre_names = request.data
        genre_models = Genre.objects.filter(name__in=genre_names)
        adventure = self.get_object()
        adventure.genre_set.set(genre_models)
        adventure.save()
        serializer = AdventureSerializer(adventure)
        return JsonResponse(serializer.data)

序列化器.py

class AdventureSerializer(serializers.ModelSerializer):
    genre_set = serializers.StringRelatedField(many=True, read_only=True)
    character_set = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    location_set = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    storyboard = serializers.PrimaryKeyRelatedField(read_only=True)
    theme = serializers.PrimaryKeyRelatedField(queryset=Theme.objects.all())

    class Meta:
        model = Adventure
        fields = '__all__'

混合

# this is a dictionary used to default brainstorm data each time an adventure is created
default_brainstorm = {
    "nodes": [...],
    "edges": [...]
}

最佳答案

您可以在新的序列化器字段中覆盖 to_internal_valueto_representation 来处理 JSON 字段的返回数据。

class JSONSerializerField(serializers.Field):
    """Serializer for JSONField -- required to make field writable"""

    def to_internal_value(self, data):
        return data

    def to_representation(self, value):
        return value

然后,您将在序列化程序中使用此字段:

class SomeSerializer(serializers.ModelSerializer):
    json_field = JSONSerializerField()

    class Meta:
        model = SomeModelClass
        fields = ('json_field', )

这应该可以解决您的问题:)

关于python - JSONField 对于 POST 序列化为 json,对于 GET 序列化为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47205238/

相关文章:

json - 告诉 typescript 编译json文件

html - 在 html/css/django 中制作一个 div-row 折叠

python - 如何在 Spyder 4 中运行选定的线路?

python - Matplotlib/python 可点击点

php - 将 SQL/PHP 中的日期输入格式从 Y/M/D 更改为 D/M/Y

python - 如何将验证错误显示为 django admin 默认错误

python - 为什么我的第二个函数没有返回任何内容?

java - Android (Java) HTTP POST JSON 到服务器,但服务器告诉我没有看到 POST 变量

python - 为什么Django Channels Daphne不能使用多线程并发处理请求?