前提・実現したいこと
以下のようなテーブル構成で、Many to Many のリレーションを作っています。
productsテーブル
Column | description |
---|---|
product_id | 商品ID |
title | 商品名 |
genresテーブル
Column | description |
---|---|
genre_id | ジャンルID |
genre_name | ジャンル名 |
products_in_genresテーブル
(中間テーブル)
Column | description |
---|---|
product_id | 商品ID |
genre_id | ジャンル名 |
そして、DBへの登録処理を下記のようなコードで行おうとしています。
- IDからデータを取得(商品に紐づいた、ジャンル一覧も取得できる)
- 商品マスタ情報の設定
- ジャンルマスタ情報の設定
- 商品マスタとジャンルマスタ、中間テーブルを一度に登録
python
1class ProductGenre(db.DbBase): 2 __tablename__ = 'products_in_genres' 3 4 product_id = Column(String(20), 5 ForeignKey('dsc_products.product_id', ondelete="CASCADE", onupdate="CASCADE"), 6 primary_key=True, comment='商品ID') 7 genre_id = Column(String(10), 8 ForeignKey('dsc_genres.genre_id', ondelete="CASCADE", onupdate="CASCADE"), 9 primary_key=True, comment='ジャンルID') 10 11 12class Products(db.DbBase): 13 __tablename__ = "products" 14 15 product_id = Column(String(20), primary_key=True, comment='商品ID') 16 title = Column(String(300), nullable=False, comment='タイトル名') 17 genres = relationship('Genres', secondary=ProductGenre.__tablename__) 18 19 20class Genres(db.DbBase): 21 22 __tablename__ = 'genres' 23 24 genre_id = Column(String(10), primary_key=True, comment='ジャンルID') 25 genre_name = Column(String(50), nullable=False, comment='ジャンル名') 26 products = relationship('Products', secondary=ProductGenre.__tablename__) 27 28 29def product_register(info: dict) -> None: 30 """ 31 登録処理 32 """ 33 # 2.商品マスタ情報の設定 34 product = Products() 35 product.product_id = info.get('product_id') 36 product.title = info.get('title') 37 38 # 3.ジャンルマスタ情報の設定 39 genres_list = list() 40 for genre_id, genre_name in info.get('genres').items(): 41 genre = Genres() 42 genre.genre_id = genre_id 43 genre.genre_name = genre_name 44 45 genres_list.append(genre) 46 # 4.商品マスタとジャンルマスタ、中間テーブルを一度に登録 47 product.genres = genres_list 48 db.session.add(product) 49 db.session.commit() 50 51if __name__ == '__main__': 52 info = get_product_info("AAAA") #1 53 product_register(info) 54 info = get_product_info("BBBB") #1 55 product_register(info) 56 57
発生している問題
当然、同一のジャンルIDが複数の商品IDに紐づきます。
1つ目のデータでは問題なく3テーブルに一度に登録できます。
2つ目以降で、登録済みのジャンルIDを登録しようとするとキー重複エラーとなってしまします。
もちろん、
ジャンルマスタ
↓
商品マスタ
↓
中間テーブル
の順番にinsertすることでは実現できます。
しかし、上記コードのようにリレーションを定義しており、1レコード目のように3テーブルを一括で登録できれば便利です。
キーがすでにあれば、重複したデータのみ関連マスタにはinsertしないというようなことはできないのでしょうか?
よろしくお願いいたします。
あなたの回答
tips
プレビュー