以下のような構成のTable、ModelSerializerで新規登録、更新する実現するための実装サンプル
- Table_A_Serilaizer で create、updateをオーバーライドする
- オーバーライドした create、update で validated_data から table_b を抜き出す
- create() では先にTable_A へvalidated_data で createを行い、id を生成してから Table_Bへの save を行う
- update() はTable_A へvalidated_data で update、抜き出した data で Table_Bへの save を行う
- view で Table_A_Serilaizer を生成する際、
partial=True
を付ける- 新規登録時に validation で エラーになることを避けるため
view
# 登録するデータ
data = {
'value_1': 100
'table_b': {
'value_2': 200
}
}
# 新規登録時
serializer = Table_A_Serilaizer(data=data, partial=True)
# 更新時
before = Table_A.objects.get(id=id)
serializer = Table_A_Serilaizer(instance=before, data=data, partial=True)
# 登録処理
serializer.is_valid()
serializer.save()
serializer
class Table_B_Serilaizer(ModelSerializer):
class Meta:
model = Table_B
fields = '__all__'
class Table_A_Serilaizer(ModelSerializer):
table_b = Table_B_Serilaizer()
class Meta:
model = Table_A
fields = '__all__'
def create(self, validated_data):
# validated_data から table_b を抜き出す
data = validated_data.pop('table_b')
# Table_Aのcreate
table_a = super().create(validated_data)
# Table_Bのsave
table_a.table_b = self.__save_table_b(table_a, data)
return table_a
def update(self, instance, validated_data):
# validated_data から table_b を抜き出す
data = validated_data.pop('table_b')
# Table_Bのsave
self.__save_table_b(instance, data)
# Table_Aのupdate
return super().update(instance, validated_data)
def __save_table_b(self, instance, data):
data['id'] = instance.id
if hasattr(instance, 'table_b'):
table_b = Table_B_Serilaizer(instance=instance.table_b, data=data)
else:
table_b = Table_B_Serilaizer(data=data)
table_b.is_valid()
table_b.save()
model
class Table_A(models.Model):
id = models.AutoField(primary_key=True)
value_1 = models.IntegerField()
class Table_B(models.Model):
id = models.AutoField(primary_key=True)
table_a_id = models.OneToOneField(Table_A, on_delete=models.CASCADE)
value_2 = models.IntegerField()