Djangoroidの奮闘記

python,django,angularJS1~三十路過ぎたプログラマーの奮闘記

AngularJS1 + Django REST Frameworkに再挑戦 その7 Comment Create API Endpoint & Serializer Context

概要

AngularJS1 + Django REST Frameworkに再挑戦 その7 Comment Create API Endpoint & Serializer Context

参考動画

Django + AngularJS | Coding For Entrepreneurs

Comment Create API Endpoint & Serializer Context

  • http://127.0.0.1:8000/api/comments/create/にアクセスして、apiを作成しようとしても、valid errorが表示されて、作成できない。なので、serializerを変更する。

  • comments/api/serializers.pyの、class CommentCreateSerializer(ModelSerializer):をコピペして独立させる。

  • 以下のように追記する。

from rest_framework import serializers
...
class CommentCreateSerializer(ModelSerializer):
    type = serializers.CharField(write_only=True) #Post
    slug = serializers.SlugField(write_only=True) #new-title
    parent_id = serializers.IntergerField(required=False) # comment自体が親になる可能性もあるため
...
  • def __init__の初期化メソッドの箇所は丸々削除する。

  • class Metaのfieldsを追記する。後、validate以下は一旦コメントアウトする。

fields = [
        'id',
        'content',
        'type',
        'slug',
        'parent_id',
        'timestamp',
    ]
  • まあ普通のserializerに戻したという感じで、ここから新たにserializerの機能を追加していく。

  • def validateを以下のように修正する。

def validate(self, data):
      model_type = data.get("type", "post")
      model_qs = ContentType.objects.filter(model=model_type)
      if not model_qs.exists() or model_qs.count() != 1:
          raise ValidationError("This is not a valid content type")
      SomeModel = model_qs.first().model_class()
      slug = data.get("slug")
      obj_qs = SomeModel.objects.filter(slug=slug)
      if not obj_qs.exists() or obj_qs.count() != 1:
          raise ValidationError("This is not a slug for this content type")
      parent_id = data.get("parent_id")
      if parent_id:
          parent_qs = Comment.objects.filter(id=parent_id)
          if not parent_qs.exists() or parent_qs.count() != 1:
              raise ValidationError("This is not a valid parent for this content")
      return data
  • def createも同じように、validated_dataを利用して、書き換える。
def create(self, validated_data):
      content = validated_data.get("content")
      if user:
          main_user = user
      else:
          main_user = User.objects.all().first()
      model_type      = validated_data.get("type", "post")
      slug            = validated_data.get("slug")
      parent_id       = validated_data.get("parent_id")
      parent_obj      = None
      if parent_id:
          parent_obj = Comment.objects.filter(id=parent_id).first()

      comment = Comment.objects.create_by_model_type(
              model_type, slug, content, main_user,
              parent_obj=parent_obj,
              )
      return comment
  • comments/api/views.pyのCommentCreateAPIViewを修正する。一旦シンプルな形に戻す。
class CommentCreateAPIView(CreateAPIView):
    queryset = Comment.objects.all()
    serializer_class = CommentCreateSerializer
  • CommentCreateAPIViewに、contextを追記する。(get_serializer_contextを上書きする)
class CommentCreateAPIView(CreateAPIView):
    queryset = Comment.objects.all()
    serializer_class = CommentCreateSerializer

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context['user'] = self.request.user
        return context
  • なぜ、userをわざわざcontextで渡すかというと、CommentCreateSerializerの方で、使いたいらしい。
def create(self, validated_data):
      content         = validated_data.get("content")
      model_type      = validated_data.get("type", "post")
      slug            = validated_data.get("slug")
      parent_id       = validated_data.get("parent_id")
      parent_obj      = None
      if parent_id:
          parent_obj = Comment.objects.filter(id=parent_id).first()
      user            = self.context['user']
      comment = Comment.objects.create_by_model_type(
              model_type, slug, content, user,
              parent_obj=parent_obj,
              )
      return comment
  • ここまでセットしたら、http://127.0.0.1:8000/api/comments/create/でコメントを作成してみる。。。。無事表示された〜!