Back to Blog

Flaskのモデル(Model)の使い方について詳しく解説

flask

2024年7月12日

こんにちは!

今回の記事では、Flaskのモデル(Model)の使い方について詳しく解説します。

モデルとはそもそもなんなのか、モデルの定義方法、プロパティやセッター、カスタムバリデーションの設定方法などを詳しく解説します。

モデルとは?

そもそもモデルとは何なのでしょうか?

モデルとは、データベース内のデータの構造を定義するためのものです。

Flaskアプリケーションにおいて、モデルはビジネスロジックとデータベースの間の橋渡し役を担います。

モデルの定義方法

FlaskではSQLAlchemyというORM(Object Relational Mapper)を使用して、Pythonのクラスとしてモデルを定義します。

SQLAlchemyを使うことで、SQL文を直接書かずにPythonコードでデータベース操作が可能になります。

Flask SQLAlchemyの使い方については、こちらの記事で詳しく解説しています。

【関連記事】Flask-SQLAlchemyとは?FlaskでDBを使おう

モデルの定義は、以下のように記述します。ファイルはapp.pyもしくは、models.pyに記述します。

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

モデルの定義方法についてさらに詳しく解説します。

クラスの宣言

まず、モデルの一行目は、クラスの宣言です。

SQLAlchemyでは、クラスとしてモデルを定義するためです。

書式は以下の通りです。

class [モデル名](db.Model):

モデル名は先頭が大文字で定義するのが一般的です。デフォルトでは、モデル名を小文字にしたものがテーブル名として使用されます。

例えば、モデル名をUserと定義した場合、テーブル名はuserとなります。

テーブル名を明示的に指定したい場合は、tablename属性を使用して定義します。

class User(db.Model):
   __tablename__ = 'users'  # テーブル名を 'users' に指定

テーブルのカラム定義

次にテーブルカラムの定義です。書式は以下の通りです。

class [モデル名](db.Model):
  [カラム名] = db.Column(データ型, 制約1, 制約2, ...)

カラムのデータ型には、以下のようなものが使われます。

データ型説明
db.Integer整数型
db.String(size)サイズ指定の文字列型
db.Text長い文字列
db.Float浮動小数点数
db.Boolean真偽値
db.Date日付
db.DateTime日時
db.Time時刻
db.LargeBinaryバイナリデータ

カラムには以下のような制約やオプションを設定することができます。

設定説明
primary_keyプライマリキー。Trueにするとそのカラムがプライマリキーになります。
unique一意制約。Trueにするとそのカラムの値が一意であることを保証します。
nullableNULLを許可。FalseにするとそのカラムはNULLを許可しません。
defaultデフォルト値。カラムのデフォルト値を設定します。
indexインデックス。Trueにするとそのカラムにインデックスを作成します。
ForeignKey外部キー制約。別のテーブルのカラムを参照します。

これらの設定値を組み合わせて、カラムの定義を行います。

例えば、以下のようなモデルを定義したとします。

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

この場合、カラムは以下のようになります。

  • id: 整数型でプライマリキー。
  • username: 最大80文字の文字列型、一意制約付き、NULL許可なし。
  • email: 最大120文字の文字列型、一意制約付き、NULL許可なし。

このようにカラムを定義します。

外部制約の定義

外部キー制約とは、データベースにおいて、あるテーブルのカラム(外部キー)が別のテーブルのプライマリキーや一意キーを参照することを保証するための制約です。

これにより、テーブル間の参照整合性を確保し、関連するデータが一貫して管理されます。

例えば、以下のようなモデルがあったとします。

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    #リレーションシップを定義し、ユーザーが持つポストを関連付け
    posts = db.relationship('Post', back_populates='user')

class Post(db.Model):
    __tablename__ = 'posts'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    body = db.Column(db.Text, nullable=False)
    #usersテーブルのidカラムを参照する外部キー制約を持つカラム
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    #レーションシップを定義し、ポストを所有するユーザーを関連付け
    user = db.relationship('User', back_populates='posts')

これは、ユーザー(User)と記事(Post)のモデルを定義したものです。

Userクラスのposts属性とPostクラスのuser属性は、db.relationshipを使用して関連付けられています。これにより、ユーザーとそのポストとの間に1対多のリレーションシップが確立されます。
back_populatesを使用することで、双方向のリレーションシップが定義され、どちらのクラスからも関連するオブジェクトにアクセスできます。

プロパティ(@property)

モデルには、プロパティを設定することができます。

プロパティを設定することで、モデルの属性に対して追加のロジックを実装することができます。

例えば、passwordはプログラムから読み取れないようにするといったロジックを追加できます。

プロパティは、@propertyデコレータを使用して定義します。

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    _password = db.Column('password', db.String(255), nullable=False)

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

上記の例では、passwordという属性を定義していますが、読み取り専用にするためにAttributeErrorを発生させています。これにより、user.passwordのようにアクセスするとエラーが発生します。

ちなみに、カラム名(_password)にプレフィックスとしてアンダースコア(_)を付けるのは、プライベート属性や内部でのみ使用される属性であることを示すためです。これはPythonの命名規則の一部で、クラス内でのカプセル化を表現するために使用されます。

セッター(@propertyname.setter)

@propertyname.setterデコレータを使用すると、プロパティに対してカスタムセッターを定義できます。セッターを設定することで、値を設定する際に追加のロジックを実行できます。

例えば、パスワードを設定する際に、ハッシュ化するといったロジックを追加できます。

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    _password = db.Column('password', db.String(255), nullable=False)

    @password.setter
    def password(self, password):
        self._password = generate_password_hash(password)

上記の例では、passwordというプロパティにセッターを定義しています。

user.password = ‘new_password’のように値を設定すると、自動的にgenerate_password_hash関数を使ってパスワードのハッシュが生成され、_passwordカラムに格納されます。

カスタムバリデーション

モデルの定義では、カラムに対するカスタムバリデーションを定義することもできます。

カスタムバリデーションとは、データベースモデルにおいて、特定の条件を満たすようにデータを検証するためのカスタムロジックを追加することを指します。

これにより、データの整合性や一貫性を確保し、不正なデータが保存されるのを防ぐことができます。

例えば、メールには必ず@が必要といったデータの規則を設定することです。

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(150), unique=True, nullable=False)

    @validates('email')
    def validate_email(self, key, email):
        if '@' not in email:
            raise ValueError("Invalid email address")
        return email

@validates(‘email’) デコレータは、emailフィールドの変更を監視し、validate_emailメソッドを呼び出します。
validate_emailメソッドでは、@が含まれていないメールアドレスを検出すると、ValueErrorを発生させます。

このようにカスタムバリデーションを設定して、データの整合性を保ちます。

まとめ

今回の記事では、FlaskのModel(モデル)について詳しく解説しました。

モデルの定義は、Webアプリケーションを開発する上で必要な設定です。Modelにはプロパティやセッターなどさまざまな設定をすることが可能です。

今回の記事で解説した内容を踏まえて、適切にモデルの設計を行いましょう。

本記事があなたのWeb開発のお役に立てれば幸いです。

ここまでお読みいただきありがとうございました。

             

Pythonの基礎から応用まで学べる
Python WebAcademy

Python WebAcademyでは、Pythonの基礎からアーキテクチャなどの応用的な内容まで幅広く学べます。また、ブラウザ上で直接Pythonコードを試すことができ、実践的なスキルを身につけることが可能です。

無料で試す