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

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

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

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

Python 3.x

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

SQLAlchemy

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

Q&A

解決済

1回答

740閲覧

SQLAlchemyのリレーションでULIDをデフォルトにしたときユニーク制約でエラーが出る

tom1022

総合スコア6

Flask

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

Python 3.x

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

SQLAlchemy

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

0グッド

0クリップ

投稿2023/03/06 11:18

実現したいこと

  • SQLAlchemyのリレーションでULIDを使う

前提

使用するモジュールは以下のとおりです

  • Flask
  • Flask-Login
  • SQLAlchemy
  • ulid-py

発生している問題・エラーメッセージ

sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: roles.ulid [SQL: INSERT INTO roles (ulid, name) VALUES (?, ?)] [parameters: ('01GTV995JF912S32TC2QG6N5WB', 'User')] (Background on this error at: https://sqlalche.me/e/14/gkpj)

該当のソースコード

テーブルの定義

python

1class USER_ROLE(db.Model): 2 __tablename__ = 'user_role' 3 user_id = db.Column(db.Integer(), ForeignKey('users.ulid', ondelete='CASCADE'), primary_key=True) 4 role_id = db.Column(db.Integer(), ForeignKey('roles.ulid', ondelete='CASCADE'), primary_key=True) 5 6class USERS(db.Model, UserMixin): 7 __tablename__ = 'users' 8 9 ulid = db.Column(db.Text(26), primary_key=True, default = ulid.new().str) 10 name = db.Column(db.String(100), unique = True) 11 password = db.Column(db.String(100)) 12 display_name = db.Column(db.String(100)) 13 14 # Relationships 15 pages = db.relationship('PAGES', secondary=UP.__tablename__, back_populates='author') 16 roles = db.relationship('ROLES', secondary='ur') 17 18class ROLES(db.Model): 19 __tablename__ = 'roles' 20 ulid = db.Column(db.Text(26), primary_key=True, default = ulid.new().str) 21 name = db.Column(db.String(50), unique=True)

初期化

python

1@app.before_first_request 2def init(): 3 try: 4 tables.USERS.query.filter(tables.USERS.name=="admin").one_or_none() 5 except Exception: 6 db.create_all() 7 admin_role = tables.ROLES(name='Admin') 8 db.session.add(admin_role) 9 db.session.commit() 10 user_role = tables.ROLES(name='User') 11 db.session.add(user_role) 12 db.session.commit() 13 admin = tables.USERS( 14 name='admin', 15 display_name='Administrator', 16 password=generate_password_hash('password') 17 ) 18 admin.roles = [admin_role, student_role] 19 db.session.add(admin) 20 db.session.commit()

試したこと

初期化する部分のプログラムを特に見直しましたが同じロールを追加しているわけでもないので全く原因がわかりませんでした。

検証すればいいことがわからなかったので情報が少ないかもしれませんがよろしくお願いします

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

下記の、ulidのdefaultの設定が正しくないです。

python

1class USERS(db.Model, UserMixin): 2 ulid = db.Column(db.Text(26), primary_key=True, default = ulid.new().str) 3 4class ROLES(db.Model): 5 ulid = db.Column(db.Text(26), primary_key=True, default = ulid.new().str)

defaultで、毎回新しいulidを作りたいのだと思うのですが、この書き方だと、先に ulid.new()で固定のulidを作成してしまって、そのstrの値をdefault値に設定するという意味になります。なので、コンストラクタで値を渡さなければ、すべて同じ値が使われます。

毎回、新しいulidを作成したい場合は、defaultに関数などのcallableをセットします。(lambdaで書いてもいいと思います)

python

1def ulid_new_str(): 2 return ulid.new().str 3 4class USERS(db.Model, UserMixin): 5 ulid = db.Column(db.Text(26), primary_key=True, default=ulid_new_str)

投稿2023/03/06 12:42

bsdfan

総合スコア4571

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tom1022

2023/03/07 07:33

問題なく動作しました ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問