DRFのnestedに書き込みができなかった話
プライマリーキーではないが、ユニーク属性のカラムに外部キーを張っていた際に、DRFにネストした状態で一括で保存ができなかった。
viewからSeriializerに渡されるデータは以下を想定している。また、UserSerializerはネスト状態で、子要素の書き込みも同時に行えるようにcreateメソッドをオーバーライドしておいた。
{ "not_pk": "abc123", "name: "tanaka", "description": { "maximo": "when you are in Rome..." } }
class User(Model): not_pk = CharField(null=False, unique=True... class UserDescription(Model): user = ForeignKey(User, related_name="description",...
class UserDescriptionSerializer(ModelSerializer): class Meta: model = UserDescription fields = "__all__" class UserSerializer(ModelSerializer): description = UserDescriptionserializer() class Meta: model = User fields = "__all__" def create(self, validated_data): user_description_data = validate_data.pop("user_description) user = User.objects.create(**validated_data) UserDescription.objects.create(user=user, **user_description_data) return user
理想でいけばこのままで動くはずだったのだが、postリクエストを投げると以下のようなエラーがでた。
{"description":{"user":["This field is required."]}}
ちなみに、エラーの発生はUserSerialierのcreateより前である。この理由としては、DRFのシリアライザーがデータを受け取ってからcreateメソッドを実行するまでの間に、各フィールに対してのバリデーションをかけるからである。(現場で使えるDjango REST frameworkの教科書 第3章 シリアライザ 参照のこと
そこで、UserSerializerにデシリアライズをするときにuser(必須フィールド)に対してrequired=False
オプションを与えバリデーションをかけないようにすることで回避した。
class UserDescriptionSerializer(ModelSerializer): user = PrimaryKeyRelatedField(queryset=User.objects.all(), required=False) class Meta: model = UserDescription fields = "__all__"