2017-11-09 9 views
1

私のコードには非常に単純な問題がありますが、この問題に対して数日間頭を落としてしまいました。JSONFieldはPOSTのjsonとしてシリアル化されますが、GET用の文字列

重要パッケージ:ここ

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 

は何が起こっているかである。

私は私のサーバーが正しくbrainstorm_dataをシリアライズAJAX呼び出し

enter image description here

を経由してモデルを作成 json objeとしてのフィールドct。

今、私は次のページに私のユーザーをナビゲートし、現在のモデルにいくつかの理由で

enter image description here

をフェッチ、brainstorm_dataは、現在の文字列として返されています。このリソースでGETリクエストを呼び出すたびに、私はいつもJSONオブジェクトの文字列表現を取得します。ここ

は、関連付けられたコードである:

models.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) 

serializers.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": [...] 
} 
+0

私の問題は、 'jsonb'とは対照的に、 'text'である基になるデータベース列から生じると思います。新しいクラス "ABC"を作成してJSONFieldを移行すると、それは 'jsonb'列になりますが、前の列と比較すると 'text'になります。 –

答えて

2

あなたはJSONフィールドの戻りデータを処理するために、新しいシリアライザフィールドにto_internal_valueto_representationを上書きすることができます。

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

これはあなたの問題を解決する必要があります:)

+0

はい、それは私の問題を解決しましたが、私は問題の根本原因を発見しました。私が最初に列を作成したとき、私は別のjsonフィールドパッケージでそれを行いました。基本DB列は** JSONではなく** text **です。新しい列を作成し、データを移行し、データを元に戻すと、データベースは一定の順序で元の状態に戻ります。 –

+0

素晴らしいですよ。私はMySQLでJSONフィールドと同様の問題を抱えていて、他のパッケージを使用していて、一緒に "ハック"していました –

0

私はもともと私は違うとそれをやったの列を作成jsonフィールドパッケージ。ベースのDB列は、の代わりにのテキストのjsonまたはjsonbの代わりに実際にはでした。新しい列(django jsonフィールド)を作成し、データを移行してからデータを元に戻すと、データベースは一定の順序で元に戻ります。

関連する問題