この作りが良いのかどうかは別にして、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
基本的には、こんな感じで使っています。便利に使ってくれると嬉しいです。