質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

解決済

SQLAlchemyにおいての重複データのupsert

DoryHeadech
DoryHeadech

総合スコア2

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

1回答

0評価

2クリップ

587閲覧

投稿2022/04/29 15:14

flaskでwebアプリ制作しながらプログラミングの勉強をしています
現在持っているデータをどのようにdbに登録すればいいのか、お教えください。

使用
  1. Flask-SQLAlchemy
  2. sqllite3

持っているデータ

titleactmaker
タイタニックディカプリオ20世紀fox
タイタニックケイト・ウィンスレット 20世紀fox
アイアンマンRobert John Downey Jr.パラマウント
アイアンマングウィネス・パルトローパラマウント
アイアンマン3Robert John Downey Jr.ディズニー
アベンジャーズRobert John Downey Jr.ディズニー

想定したdbの設定

  1. titleーact ; many to many → 中間テーブル(appearance)
  2. title-maker ; one to many

flaskSQLAlchemyのドキュメントを参考に

appearance = db.Table('appearance', db.Column('act_id', db.Integer, db.ForeignKey('act.id'), primary_key=True), db.Column('detail_id', db.Integer, db.ForeignKey('detail.id'), primary_key=True)) class Act(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50),unique=True) class Maker(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50),unique=True) class Detail(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(80), nullable=False,unique=True) act = db.relationship("Act",secondary=appearance) maker_id = db.Column(db.Integer, db.ForeignKey('maker.id')) maker = db.relationship('Maker', backref=db.backref('makers', lazy=True)) d=Detail(title=t, maker=m,act=[a]) db.session.add(s) db.session.commit()

このように設定しました。
次にデータを登録するために

for文で回して登録しようと思い

s=Detail(title=t, maker=m,act=[a]) db.session.add(s)

試してみると重複のため登録できませんでした
色々、調べて2つの方法を試しました。

ユニーク制約を外す

ユニーク制約を外すと重複されて登録されてしまう
→リレーションdbの意味がない?持っているデータとあまり変わらない?

upsertで登録作業をする

def upsert_stmt(): stmt = insert(Detail) return stmt.on_conflict_do_update( index_elements=['id'], set_={ 'title': stmt.excluded.title, 'maker': stmt.excluded.maker, 'act': stmt.act }) db.session.execute(stmt) #エラー IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed db.session.add(stmt) #エラー UnmappedInstanceError: Class 'sqlalchemy.dialects.postgresql.dml.Insert' is not mapped

https://qiita.com/nsuhara/items/86570f789093222252b1

def suffix_insert(insert, compiler, **kwargs): stmt = compiler.visit_insert(insert, **kwargs) if insert.dialect_kwargs.get('sqlite_on_conflict_do_nothing'): stmt += ' ON CONFLICT DO NOTHING' return stmt Insert.argument_for('sqlite', 'on_conflict_do_nothing', False) some_random_values = detail stmt = db.insert(Detail, sqlite_on_conflict_do_nothing=True).values(some_random_values) db.session.execute(stmt) #エラー CompileError: Unconsumed column names

https://stackoverflow.com/questions/64900812/how-to-use-sqlites-upsert-or-on-conflict-with-flask-sqlalchemy
→リレーション関係ところの設定がうまくいっていない?

upsertの方法はエラーがでてうまくいきませんでした

質問は
重複をもつデータのリレーションな関係で登録する方法です。
どうすれば、簡単に登録できるのかお願い致します。
(そもそもの方向性があっているのか、もし間違っていたらそのプロセスもお教えください。)

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

68user

2022/04/30 15:29 編集

そもそも何がしたいのかがいまいちつかめないのですが、持っているデータは非正規形であるので DB は正規化したいんですよね。しかし Detail は非正規形? 持っているデータから、  title_id, title  act_id, act  maker_id, maker  + 紐づけテーブル なデータを作って、それを各テーブルに突っ込んで、Detail は作らない、ではダメなんでしょうか。 ↑のデータを作るとは以下のようなものを想定しています。別に DB を絡めなくても、データを順に舐めて新しいものが出てきたら通番を振るだけ (dict などで管理する)。 title_id, title 1:タイタニック 2:アイアンマン 3:アイアンマン3 act_id, act 1:ディカプリオ 2:ケイト・ウィンスレット  3:Robert John Downey Jr. 4:グウィネス・パルトロー 上記ができたら title テーブルなり act テーブルなりに突っ込むだけ。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。