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__"