LoginSignup
1
2

More than 3 years have passed since last update.

DRF(Django REST Framework)でSerializerからViewの情報にアクセスしたいときもある件

Posted at

この作りが良いのかどうかは別にして、SerializerからViewの情報にアクセスしたい時ってありますよね。そんな時に使える便利なMixinを社内では使いまわしています。やればやるほど、ViewとSerializerとの結合が強くなるので、 用法・用量 を守って使うのをオススメします。

何はともあれ、ソースコードです。

ViewAccessSerializerMixin

class ViewAccessSerializerMixin(object):

    def get_view_action(self):
        """
        Serializer から View の actionへアクセスする
        """
        context = getattr(self, 'context')
        if not context:
            warnings.warn('serializerにcontextが存在しません。不正な形でインスタンスが作られています')
            return None
        return context.get('view').action

    def get_view_kw(self, key, default=None):
        """
        Serializer から View の kwargsへアクセスする
        """
        context = getattr(self, 'context')
        if not context:
            warnings.warn('serializerにcontextが存在しません。不正な形でインスタンスが作られています')
            return default
        return context.get('view').kwargs.get(key, default)

    def get_kwargs_object(self, key, model_class):
        """
        Serializer から kwargs へアクセスし、それを id とみなして、指定されたモデルを検索する
        """
        obj = model_class.objects.get_or_none(id=int(self.get_view_kw(key, 0)))
        if obj:
            return obj

View の action へアクセスする

大体は、 validationで使ってます。多分もっと良い条件分けはあると思います。こんな感じ。

class HogeSerializer(ViewAccessSerializerMixin, serializers.ModelSerializer):

    # 色々省略

    def validate(self, attrs):
        # アクションによって検証内容を変える
        action_name = self.get_view_action()
        if action_name == "xxxx":
            pass
        else:
            pass

View の kwargs へアクセスする

大体、SerializerMethodField で使ってます。

class PostHistorySerializer(ViewAccessSerializerMixin, serializers.ModelSerializer):

    # 色々省略

    comments = serializers.SerializerMethodField()

    def get_comments(self, obj):
        return obj.comment.filter(user_id=self.get_view_kw("user_pk"))

View の kwargs へアクセスし、それを id とみなして、指定されたモデルを検索する

↑の組み合わせに近いですが、ショートカットです。

class UserSerializer(ViewAccessSerializerMixin, serializers.ModelSerializer):

    # 色々省略

    def validate(self, attrs):
        user = self.get_kwargs_object('user_pk', models.User)
        if user.is_ban():
          raise NotFound()
        pass

基本的には、こんな感じで使っています。便利に使ってくれると嬉しいです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2