初めに
リレーションの関係を持ったDBにて新規登録、更新処理を実現するための方法を紹介します。
現在、DRF(Django Rest Framework)を使用してAPIを作成しており、ManyToManyの関係を持ったDBへの新規・更新処理を実現しようとしています。
DRFのドキュメントを基に実装を進めたものの、リレーションを持ったDBの処理に関しての記事がなかったため今回まとめました。
同じように困っている方の助けとなれれば幸いです。
ちなみに単一のDB更新に関してはこちらから
環境
- Python 3.8
- Django 3.1.3
- DRF 3.12.2
実装
前提条件
今回テストとして使用するモデルは以下の通りです。
「飲み物マスタ」と「自販機一覧」はM2Mの関係と言えます。
その理由として、
自販機から見れば飲み物は1個以上登録が必要であり、
飲み物マスタから見れば0個以上の自販機に登録されているからです。
本当はこれらの中間テーブルが存在しているのですが、DRFでは勝手に作成してくれるので、何も記載していません。
ソースコード
さて、前提条件にて記載したテーブルへ自販機を登録するAPIを作成していきます。
今回はmodel, serializerのみのソースとなります。
URLの設定などは以下をご参照いただけると幸いです。
models.py
from django.db import models
# Create your models here.
class Drinking(models.Model):
name = models.CharField(max_length=50)
temperature_flg = models.CharField(max_length=1)
def __str__(self):
return self.name
class VendorInfo(models.Model):
address = models.CharField(max_length=200)
longitude = models.DecimalField(max_digits=17, decimal_places=14)
latitude = models.DecimalField(max_digits=17, decimal_places=14)
created_at = models.DateField(auto_now=True)
Drinkings = models.ManyToManyField(Drinking)
def __str__(self):
return self.address
serializer.py
from ctypes import addressof
from multiprocessing import context
from rest_framework import serializers
from jobs.models import Drinking, VendorInfo
class VendorInfoSerializer(serializers.ModelSerializer):
Drinkings = DrinksSerializer(many=True)
class Meta:
model = VendorInfo
fields = '__all__'
def create(self, validated_data):
newVendor = VendorInfo.objects.create(
address = validated_data["address"],
latitude = validated_data["latitude"],
longitude = validated_data["longitude"],
# Drinkings = validated_data["Drinkings"],
)
newVendor.save()
for drink in validated_data["Drinkings"]:
drinkObj = Drinking.objects.get(
name = drink["name"],
temperature_flg = drink["temperature_flg"])
newVendor.Drinkings.add(drinkObj)
return newVendor
def update(self, instance, validated_data):
instance.address = validated_data["address"]
instance.latitude = validated_data["latitude"]
instance.longitude = validated_data["longitude"]
instance.save()
vendor = VendorInfo.objects.get(id=instance.id)
vendor.Drinkings.clear()
for drink in validated_data["Drinkings"]:
drinkObj = Drinking.objects.get(
name = drink["name"],
temperature_flg = drink["temperature_flg"])
instance.Drinkings.add(drinkObj)
return instance
基本的にはINSERTとUPDATEメソッドをオーバーライドするのですが、
M2Mの関係を持っているVendorInfoのDrinkingsへの登録や更新はfor文を使用して一つずつ、中間テーブルを作っているイメージです。
終わり
コメント