フラスコメガチュヌトリアル、パヌト4デヌタベヌス2018幎版

blog.miguelgrinberg.com


ミゲル・グリンバヌグ




<<<前 次>>>


この蚘事は、ミゲルグリヌンバヌグの教科曞の新版の第4郚の翻蚳です。 以前の翻蚳は、その関連性を長く倱いたした。


これは、Flask Mega-Tutorialシリヌズの第4版で、デヌタベヌスの操䜜方法を説明したす。


参考たでに、以䞋はこのシリヌズの蚘事のリストです。


内容

泚1このコヌスの叀いバヌゞョンをお探しの堎合は、こちらをご芧ください 。


泚2突然、このブログの私のミゲルの仕事を支持しお声を䞊げたい堎合、たたは単に蚘事を1週間埅぀忍耐がない堎合、私ミゲルグリヌンバヌグはこのガむドの完党版にパッケヌゞ化された電子曞籍たたはビデオを提䟛したす。 詳现に぀いおは、 learn.miguelgrinberg.comをご芧ください 。


この章のトピックは非垞に重芁です。 ほずんどのアプリケヌションでは、効率的に取埗できる氞続デヌタを維持する必芁があり、これがたさにデヌタベヌスの䜜成目的です。


この章のGitHubリンク Browse 、 Zip 、 Diff 。


Flaskのデヌタベヌス


既に聞いたこずがあるず思うので、Flaskはデヌタベヌスをネむティブにサポヌトしおいたせん。 これは、Flaskが意図的に自絊自足的でない倚くの分野の1぀です。これは、1぀に適応するのではなく、アプリケヌションに最適なデヌタベヌスを自由に遞択できるため玠晎らしいこずです。


Pythonには倚数のデヌタベヌスがあり、その倚くはFlaskアプリケヌションず統合されおいたす。 デヌタベヌスは、リレヌショナルモデルに察応するグルヌプずそうでないグルヌプの2぀の倧きなグルヌプに分けるこずができたす。 埌者のグルヌプはしばしばNoSQLず呌ばれ、䞀般的なSQLリレヌショナルク゚リ蚀語を実装しおいないこずを瀺しおいたす。 どちらのグルヌプにも優れたデヌタベヌス補品がありたすが、リレヌショナルデヌタベヌスは、ナヌザヌリスト、ブログ投皿などの構造化デヌタを持぀アプリケヌションに適しおいるず思いたす。構造が定矩されおいないデヌタの方が良い傟向。 このアプリケヌションは、他のほずんどのアプリケヌションず同様に、任意のタむプのデヌタベヌスを䜿甚しお実装できたすが、䞊蚘の理由から、リレヌショナルデヌタベヌスを䜿甚したす。


第3章では、最初のFlask拡匵機胜を玹介したした。 この章では、さらに2぀䜿甚したす。 1぀はFlask-SQLAlchemyです。これは、人気のSQLAlchemyパッケヌゞ Object Relational MapperたたはORMのFlaskフレンドリヌラッパヌを提䟛する拡匵機胜です。 ORMを䜿甚するず、アプリケヌションは、テヌブルやSQLではなく、クラス、オブゞェクト、メ゜ッドなどの高レベルオブゞェクトを䜿甚しおデヌタベヌスを管理できたす。 ORMの目暙は、高レベルの操䜜をデヌタベヌスコマンドに倉換するこずです。


SQLAlchemyの最良の郚分は、このORMは1぀ではなく、倚くのリレヌショナルデヌタベヌス甚であるこずです。 SQLAlchemyは、䞀般的なMySQL 、 PostgreSQL 、およびSQLiteを含むデヌタベヌス゚ンゞンの長いリストをサポヌトしおいたす。 サヌバヌを必芁ずしない単玔なSQLiteデヌタベヌスで開発を行うこずができるため、これは非垞に匷力です。そしお、実皌働サヌバヌにアプリケヌションをデプロむするずきが来るず、アプリケヌションを倉曎せずに、より信頌性の高いMySQLたたはPostgreSQLサヌバヌを遞択できたす。


Flask-SQLAlchemyを仮想環境にむンストヌルするには、必ずそれをアクティブにしおから実行しおください


(venv) $ pip install flask-sqlalchemy 

デヌタベヌスの移行


私が芋たデヌタベヌスチュヌトリアルのほずんどは、デヌタベヌスの䜜成ず䜿甚を扱っおいたすが、アプリケヌションを倉曎たたは増加する必芁があるため、既存のデヌタベヌスの曎新を䜜成する問題を適切に解決したせん。 リレヌショナルデヌタベヌスは構造化されたデヌタに集䞭しおいるため、これは困難です。そのため、既にデヌタベヌスにあるデヌタの構造を倉曎する堎合は、倉曎された構造に転送する必芁がありたす。


この章で玹介する2番目の拡匵機胜はFlask-Migrateです 。これは実際には謙虚な䜿甚人によっお䜜成されたす。 この拡匵機胜は、SQLAlchemyデヌタベヌス移行の基盀であるAlembicのFlaskラッパヌです。 デヌタベヌスの移行に取り組むず、最初は少し手間がかかりたすが、将来的にデヌタベヌスに倉曎を加えるための信頌できる方法にお金を払うのは少額です。


Flask-Migrateのむンストヌルプロセスは、他の拡匵機胜ず䌌おいたす。


 (venv) $ pip install flask-migrate 

Flask-SQLAlchemyの構成


開発䞭に、SQLiteデヌタベヌスを䜿甚したす。 SQLiteデヌタベヌスは、各アプリケヌションがディスク䞊の単䞀のファむルに保存され、MySQLやPostgreSQLなどのデヌタベヌスサヌバヌを起動する必芁がないため、小さなアプリケヌションを開発するのに最も䟿利な遞択肢です。


構成ファむルに远加する2぀の新しい構成項目がありたす。


config.py

 import os basedir = os.path.abspath(os.path.dirname(__file__)) class Config(object): # ... SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \ 'sqlite:///' + os.path.join(basedir, 'app.db') SQLALCHEMY_TRACK_MODIFICATIONS = False 

Flask-SQLAlchemy拡匵機胜は、 SQLALCHEMY_DATABASE_URI構成SQLALCHEMY_DATABASE_URIからアプリケヌションデヌタベヌスの堎所をSQLALCHEMY_DATABASE_URIたす。 第3章から芚えおいるように、環境が倉数を定矩しおいない堎合、環境倉数から構成をセットアップし、フォヌルバック倀を提䟛するこずをお勧めしたす。 この堎合、 DATABASE_URL環境倉数からデヌタベヌスURLを取埗し、定矩されおいない堎合は、 ベヌスアプリケヌション倉数にあるapp.dbずいうデヌタベヌスを構成したす。このデヌタベヌスは、 basedir倉数に栌玍されおいたす。


SQLALCHEMY_TRACK_MODIFICATIONS構成SQLALCHEMY_TRACK_MODIFICATIONSをFalseに蚭定するず、Flask-SQLAlchemy関数が無効になりたす。これは、デヌタベヌスに倉曎が加えられるたびにアプリケヌションに通知する必芁はありたせん。


デヌタベヌスは、 デヌタベヌスむンスタンスずしおアプリケヌションに衚瀺されたす 。 デヌタベヌス移行゚ンゞンにもむンスタンスがありたす。 これらは、 app/__ init__.pyのアプリケヌションの埌に䜜成する必芁があるオブゞェクトapp/__ init__.py 。


 from flask import Flask from config import Config from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate app = Flask(__name__) app.config.from_object(Config) db = SQLAlchemy(app) migrate = Migrate(app, db) from app import routes, models 

initスクリプトに3぀の倉曎を加えたした。 最初に、デヌタベヌスを衚すdbオブゞェクトを远加したした。 次に、移行メカニズムを衚す別のオブゞェクトを远加したした。 Flask拡匵機胜の䜿甚䟋をご芧ください。 ほずんどの拡匵機胜は、この2぀のように初期化されたす。 最埌に、以䞋のmodelsず呌ばれる新しいモゞュヌルをむンポヌトしたす。 このモゞュヌルは、デヌタベヌスの構造を決定したす。


デヌタベヌスモデル


デヌタベヌスに保存されるデヌタは、䞀般にデヌタベヌスモデルず呌ばれるクラスのセットで衚されたす。 SQLAlchemyのORMレベルは、これらのクラスから䜜成されたオブゞェクトを察応するデヌタベヌステヌブルの行にマッピングするために必芁な倉換を実行したす。


ナヌザヌを衚すモデルを䜜成するこずから始めたしょう。 WWW SQL Designerツヌルを䜿甚しお、ナヌザヌテヌブルで䜿甚するデヌタを衚す次の図を䜜成したした。



idフィヌルドはすべおのモデルで䞀般的に䜿甚され、䞻キヌずしお䜿甚されたす。 デヌタベヌス内の各ナヌザヌには、このフィヌルドに栌玍されおいる䞀意の識別子倀が割り圓おられたす。 ほずんどの堎合、䞻キヌはデヌタベヌスによっお自動的に割り圓おられるため、䞻キヌずしおマヌクされたidフィヌルドを指定するだけです。


username 、 emailおよびpassword_hashフィヌルドは文字列たたはデヌタベヌス甚語ではVARCHARずしお定矩され、デヌタベヌスがスペヌスの䜿甚を最適化できるように最倧長が指定されおいたす。 usernameずemailフィヌルドは䞀目瞭然ですが、 password_hashフィヌルドは泚目に倀したす。 䜜成するアプリケヌションが最高のセキュリティ掚奚事項を䜿甚しおいるこずを確認したいため、デヌタベヌスにナヌザヌパスワヌドを保存したせん。 パスワヌドの保存に関する問題は、デヌタベヌスが危険にさらされるず、攻撃者がパスワヌドにアクセスできるようになり、これがナヌザヌに損害を䞎える可胜性があるこずです。 パスワヌドを盎接蚘述する代わりに、セキュリティを倧幅に向䞊させるパスワヌドハッシュを蚘述したす 。 これは別の章のトピックになるので、今は心配しないでください。


ナヌザヌテヌブルに必芁なものがわかったので、これを新しいapp / models.pyモゞュヌルのコヌドに倉換できたす 。


 from app import db class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), index=True, unique=True) email = db.Column(db.String(120), index=True, unique=True) password_hash = db.Column(db.String(128)) def __repr__(self): return '<User {}>'.format(self.username) 

䞊蚘で䜜成されたUserクラスは、Flask-SQLAlchemyのすべおのモデルの基本クラスであるdb.Model継承したす。 このクラスは、いく぀かのフィヌルドをクラス倉数ずしお定矩したす。 フィヌルドはdb.Columnクラスのむンスタンスずしお䜜成されたす。このクラスは、フィヌルドタむプを匕数ずしお䜿甚し、他のオプションの匕数を䜿甚したす。たずえば、䞀意のむンデックス付きフィヌルドを指定できたす。これは、効率的なデヌタベヌス怜玢に重芁​​です。


__repr__メ゜ッドは、このクラスのオブゞェクトを印刷する方法をPythonに指瀺したす。これはデバッグに圹立ちたす。 以䞋のPythonむンタヌプリタヌセッションで、 __repr __()メ゜ッドの動䜜を確認できたす。


 >>> from app.models import User >>> u = User(username='susan', email='susan@example.com') >>> u <User susan> 

リポゞトリの移行を䜜成する


前のセクションで䜜成されたモデルクラスは、このアプリケヌションの初期デヌタベヌス構造たたはスキヌマ を定矩したす。 しかし、アプリケヌションの成長に䌎い、構造を倉曎する必芁がありたす。これにより、新しい゚ンティティが远加される可胜性がありたすが、芁玠を倉曎たたは削陀するこずもできたす。 AlembicFlask-Migrateで䜿甚される移行フレヌムワヌクはこれらのスキヌマを倉曎するため、デヌタベヌスを最初から再䜜成する必芁はありたせん。


この䞀芋耇雑なタスクを達成するために、Alembicは移行リポゞトリを維持したす。これは、移行スクリプトが保存されるディレクトリです。 デヌタベヌススキヌマが倉曎されるたびに、倉曎に関する詳现情報を含む移行スクリプトがリポゞトリに远加されたす。 デヌタベヌスに移行を適甚するために、これらの移行スクリプトは䜜成された順に実行されたす。


Flask-Migrateは、 flaskコマンドを介しおコマンドを発行したす。 Flaskにネむティブな埓属コマンドであるflask runを既に芋おきたした。 Flask-Migrateにより、 flask dbサブコマンドが远加され、デヌタベヌスの移行に関連するすべおが管理されたす。 それでは、 flask db init実行しお、マむクロブログの移行リポゞトリを䜜成したしょう。


 (venv) $ flask db init Creating directory /home/miguel/microblog/migrations ... done Creating directory /home/miguel/microblog/migrations/versions ... done Generating /home/miguel/microblog/migrations/alembic.ini ... done Generating /home/miguel/microblog/migrations/env.py ... done Generating /home/miguel/microblog/migrations/README ... done Generating /home/miguel/microblog/migrations/script.py.mako ... done Please edit configuration/connection/logging settings in '/home/miguel/microblog/migrations/alembic.ini' before proceeding. 

Flaskコマンドは、Flaskアプリケヌションの堎所を知るためにFLASK_APP環境倉数に䟝存しおいるこずにFLASK_APPしおFLASK_APP 。 このアプリケヌションでは、 第1章で説明されおいるように、 FLASK_APP=microblog.pyを蚭定したす。


このコマンドを実行するず、新しい移行ディレクトリが芋぀かりたす。このディレクトリには、いく぀かのファむルずバヌゞョンサブディレクトリがありたす。 これで、これらのファむルはすべおプロゞェクトの䞀郚ず芋なされ、バヌゞョン管理システムに远加する必芁がありたす。


最初のデヌタベヌス移行


移行リポゞトリを䜿甚しお、最初のデヌタベヌス移行を䜜成したす。これには、 UsersデヌタベヌスモデルにマップされたUsersテヌブルが含たれたす。 デヌタベヌス移行を䜜成するには、手動たたは自動の2぀の方法がありたす。 自動的に移行を䜜成するために、Alembicはデヌタベヌスモデルによっお定矩されたデヌタベヌススキヌマを、デヌタベヌスで珟圚䜿甚されおいる実際のデヌタベヌススキヌマず比范したす。 次に、デヌタベヌススキヌマがアプリケヌションモデルず䞀臎するこずを確認するために必芁な倉曎を移行スクリプトに入力したす。 この堎合、以前のデヌタベヌスがないため、自動移行によりUserモデル党䜓が移行スクリプトに远加されたす。 flask db migrate DB transferサブコマンドは、次の自動移行を生成したす。


 (venv) $ flask db migrate -m "users table" INFO [alembic.runtime.migration] Context impl SQLiteImpl. INFO [alembic.runtime.migration] Will assume non-transactional DDL. INFO [alembic.autogenerate.compare] Detected added table 'user' INFO [alembic.autogenerate.compare] Detected added index 'ix_user_email' on '['email']' INFO [alembic.autogenerate.compare] Detected added index 'ix_user_username' on '['username']' Generating /home/miguel/microblog/migrations/versions/e517276bb1c2_users_table.py ... done 

コマンドの出力から、Alembicが移行に含たれおいるこずがわかりたす。 最初の2行は参考情報であり、通垞は無芖できたす。 それから圌は、テヌブル'user'ず2぀のむンデックス'['email']'および '[' username ']'を芋぀けたず蚀いたす。 次に、移行スクリプトを䜜成した堎所を説明したす。 e517276bb1c2コヌドは、移行甚に自動生成された䞀意のコヌドです異なる堎合がありたす。 -mオプションで指定されたコメントはオプションであり、ハむフンに短い説明テキストを远加したす。


生成された移行スクリプトはプロゞェクトの䞀郚であり、バヌゞョン管理システムに含める必芁がありたす。 スクリプトがどのように芋えるか興味がある堎合は、スクリプトを衚瀺できたす。 upgrade()ずdowngrade() 2぀の機胜があるこずがわかりたす。 upgrade()機胜は移行を適甚し、 downgrade()機胜は移行を削陀したす。 これにより、Alembicは、ダりングレヌドパスを䜿甚しお、履歎内の任意の堎所叀いバヌゞョンでもにデヌタベヌスを転送できたす。


flask db migrateコマンドはデヌタベヌスに倉曎を加えるこずはなく、単に移行スクリプトを䜜成したす。 デヌタベヌスに倉曎を適甚するには、 flask db upgradeコマンドを䜿甚する必芁がありたす。


 (venv) $ flask db upgrade INFO [alembic.runtime.migration] Context impl SQLiteImpl. INFO [alembic.runtime.migration] Will assume non-transactional DDL. INFO [alembic.runtime.migration] Running upgrade -> e517276bb1c2, users table 

このアプリケヌションはSQLiteを䜿甚しおいるため、Upgradeコマンドはデヌタベヌスが存圚しないこずを怜出しお䜜成したすこのコマンドの完了埌にapp.dbずいう名前のファむル、぀たりSQLiteデヌタベヌスが远加されたす。 MySQLやPostgreSQLなどのデヌタベヌスサヌバヌを䜿甚する堎合、曎新を開始する前にデヌタベヌスサヌバヌにデヌタベヌスを䜜成する必芁がありたす。


デヌタベヌスのアップグレヌドプロセスず、アップグレヌドおよびダりングレヌドの倉曎のロヌルバック


珟時点では、アプリケヌションはただ初期段階にありたすが、これは将来のデヌタベヌス移行戊略に䜕が含たれるかを議論するのに支障はありたせん。 開発マシンにアプリケヌションがあり、オンラむンで䜿甚䞭の本番サヌバヌにコピヌがデプロむされおいるずしたす。


アプリケヌションの次のバヌゞョンでは、モデルに倉曎を加える必芁があるずしたす。たずえば、新しいテヌブルを远加する必芁があるずしたす。 移行を行わない堎合、ロヌカルホストずサヌバヌの䞡方でデヌタベヌスのスキヌマを倉曎する方法を理解する必芁がありたすが、これは倧きな問題になる可胜性がありたす。


ただし、デヌタベヌス移行のサポヌトでは、アプリケヌションのモデルを倉曎した埌、新しい移行スクリプトflask db migrateを䜜成したす。自動䜜成が正しいこずを確認し、開発デヌタベヌスflaskに倉曎を適甚するこずを確認したす。 db upgrade。 移行スクリプトをバヌゞョン管理システムに远加しおコミットしたす。


本番サヌバヌでアプリケヌションの新しいバヌゞョンをリリヌスする準備ができたら、必芁な䜜業は、新しい移行スクリプトを含む曎新されたバヌゞョンのアプリケヌションを取埗し、 flask db upgradeを実行するこずだけです。 Alembicは、デヌタベヌスが最新版に曎新されおいないこずを怜出し、以前のリリヌス埌に䜜成されたすべおの新しい移行スクリプトを実行したす。


前述したように、最埌の移行をキャンセルするdowngrade flask dbコマンドもありたす。 本番皌働時にこのオプションが必芁になるこずはほずんどありたせんが、開発䞭に非垞に圹立぀こずがありたす。 移行スクリプトを生成しお適甚したのは、行った倉曎が必芁なものではないこずを確認するためだけです。 この堎合、デヌタベヌスの評䟡を䞋げ、移行スクリプトを削陀しおから、新しいスクリプトを䜜成しお眮き換えるこずができたす。


デヌタベヌス関係


リレヌショナルデヌタベヌスは、デヌタ項目間の関係を保存するのに適しおいたす。 ナヌザヌがブログ投皿を曞く堎合を考えおください。 ナヌザヌはナヌザヌテヌブルに゚ントリを持ち、メッセヌゞはメッセヌゞテヌブルに゚ントリを持ちたす。 この投皿を曞いた人を蚘録する最も効果的な方法は、2぀の蚘録をリンクするこずです。


ナヌザヌず投皿の間の接続が確立された埌、必芁になる可胜性のある2皮類の芁求がありたす。 投皿があり、どのナヌザヌがそれを曞いたかを知る必芁がある堎合に最も簡単です。 もう少し耇雑な質問は、この逆です。 ナヌザヌがいる堎合は、そのナヌザヌが䜜成したすべおの゚ントリを取埗する必芁がありたす。 Flask-SQLAlchemyは、䞡方のタむプのク゚リで圹立ちたす。


投皿を保存するためのベヌスを拡匵しお、実行䞭の接続を確認できるようにしたす。 これを行うには、デヌタベヌス蚭蚈ツヌルに戻り、レコヌドのテヌブルを䜜成したす。



メッセヌゞテヌブルには、必芁な識別子、メッセヌゞテキスト、およびタむムスタンプが含たれたす。 しかし、これらの予想されるフィヌルドに加えお、メッセヌゞをその䜜成者にバむンドするuser_idフィヌルドを远加しuser_id 。 すべおのナヌザヌが䞀意の䞻キヌid持っおいるこずがわかりたした。 ブログ゚ントリを䜜成したナヌザヌに関連付ける方法は、ナヌザヌIDぞのリンクを远加するこずuser_id 。これはuser_idフィヌルドuser_idたったく同じuser_id 。 このuser_idフィヌルドは倖郚キヌず呌ばれたす。 䞊蚘のデヌタベヌスダむアグラムでは、倖郚キヌは、フィヌルドずそれが参照するテヌブルのidフィヌルドずの関係ずしお衚瀺されたす。 「1人の」ナヌザヌが「倚くの」メッセヌゞを曞き蟌むため、この皮の関係は1察倚ず呌ばれたす。


倉曎されたapp / models.pyを以䞋に瀺したす


 from datetime import datetime from app import db class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), index=True, unique=True) email = db.Column(db.String(120), index=True, unique=True) password_hash = db.Column(db.String(128)) posts = db.relationship('Post', backref='author', lazy='dynamic') def __repr__(self): return '<User {}>'.format(self.username) class Post(db.Model): id = db.Column(db.Integer, primary_key=True) body = db.Column(db.String(140)) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) def __repr__(self): return '<Post {}>'.format(self.body) 

新しいPostクラスには、ナヌザヌが䜜成したブログ投皿が含たれたす。 timestampフィヌルドにはむンデックスが付けられたす。これは、メッセヌゞを時系列で受信する堎合に䟿利です。 たた、デフォルトの匕数を远加し、関数datetime.utcnowを枡したした。 デフォルト関数を枡すず、SQLAlchemyはこの関数を呌び出すようにフィヌルドを蚭定したす() utcnow埌に()をutcnowなかったため、呌び出しの結果ではなく、この関数を自分で枡したす。 通垞、これにより、サヌバヌアプリケヌションでUTCの日付ず時刻を操䜜できたす。 これにより、ナヌザヌがどこにいおも単䞀のタむムスタンプを䜿甚できたす。 これらのタむムスタンプは、衚瀺されるずきにナヌザヌの珟地時間に倉換されたす。


user_idフィヌルドはuser.id倖郚キヌずしお初期化されたした。぀たり、 usersテヌブルのid倀を参照したす。 このリンクでは、userは、Flask-SQLAlchemyが小文字に倉換されたモデルクラスの名前ずしお自動的に蚭定するデヌタベヌステヌブルの名前です。 Userクラスには、 db.relationshipによっお初期化される新しいメッセヌゞフィヌルドがありたす。 これは実際のデヌタベヌスフィヌルドではなく、ナヌザヌず投皿の関係の高レベルのビュヌであり、このため、デヌタベヌスダむアグラムにはありたせん。 1察倚の関係の堎合、db.relationshipフィヌルドは通垞、片偎で定矩され、倚くにアクセスする䟿利な方法ずしお䜿甚されたす。 したがっお、たずえば、ナヌザヌがuに栌玍されおいる堎合、匏u.postsは、そのナヌザヌによっお曞き蟌たれたすべおのレコヌドを返すデヌタベヌスク゚リをトリガヌしたす。 db.relationshipの最初の匕数は、倚リレヌションシップのサむドを衚すクラスを指定したす。 backref匕数は、1぀のオブゞェクトを指すmanyクラスのオブゞェクトに远加されるフィヌルドの名前を指定したす。 これにより、投皿の著者を返すpost.author匏が远加されたす。 遅延匕数は、通信甚のデヌタベヌスク゚リの実行方法を決定したす。これに぀いおは埌で説明したす。 これらの詳现が意味をなさない堎合でも心配しないでください。この蚘事の最埌に䟋を瀺したす。


アプリケヌションモデルの曎新があるため、新しいデヌタベヌス移行を䜜成する必芁がありたす。


 (venv) $ flask db migrate -m "posts table" INFO [alembic.runtime.migration] Context impl SQLiteImpl. INFO [alembic.runtime.migration] Will assume non-transactional DDL. INFO [alembic.autogenerate.compare] Detected added table 'post' INFO [alembic.autogenerate.compare] Detected added index 'ix_post_timestamp' on '['timestamp']' Generating /home/miguel/microblog/migrations/versions/780739b227a7_posts_table.py ... done 

そしお、デヌタベヌスに移行を適甚する必芁がありたす。


 (venv) $ flask db upgrade INFO [alembic.runtime.migration] Context impl SQLiteImpl. INFO [alembic.runtime.migration] Will assume non-transactional DDL. INFO [alembic.runtime.migration] Running upgrade e517276bb1c2 -> 780739b227a7, posts table 

プロゞェクトがバヌゞョン管理に保存されおいる堎合は、新しい移行スクリプトを忘れずに远加しおください。


打ち䞊げ時間


長いデヌタベヌス䜜成プロセスを実行させたしたが、すべおがどのように機胜するかに぀いおはただ説明しおいたせん。 アプリケヌションにはただデヌタベヌスロゞックがないため、Pythonむンタヌプリタヌでデヌタベヌスを操䜜しお、デヌタベヌスに慣れおみたしょう。 それでは、Pythonを実行しおください。 むンタヌプリタヌを開始する前に、仮想環境がアクティブになっおいるこずを確認しおください。


Pythonコマンドラむンで、デヌタベヌスむンスタンスずモデルをむンポヌトしたしょう。


 >>> from app import db >>> from app.models import User, Post 

:


 >>> u = User(username='john', email='john@example.com') >>> db.session.add(u) >>> db.session.commit() 

, db.session . , , db.session.commit() , . , db.session.rollback() , . , db.session.commit() . , .


:


 >>> u = User(username='susan', email='susan@example.com') >>> db.session.add(u) >>> db.session.commit() 

, :


 >>> users = User.query.all() >>> users [<User john>, <User susan>] >>> for u in users: ... print(u.id, u.username) ... 1 john 2 susan 

, . — , , all() . , id 1 2.


. , :


 >>> u = User.query.get(1) >>> u <User john> 

:


 >>> u = User.query.get(1) >>> p = Post(body='my first post!', author=u) >>> db.session.add(p) >>> db.session.commit() 

timestamp , , . user_id? , db.relationship , User , posts , . , , , . SQLAlchemy , .


, :


 >>> # get all posts written by a user >>> u = User.query.get(1) >>> u <User john> >>> posts = u.posts.all() >>> posts [<Post my first post!>] >>> # same, but with a user that has no posts >>> u = User.query.get(2) >>> u <User susan> >>> u.posts.all() [] >>> # print post author and body for all posts >>> posts = Post.query.all() >>> for p in posts: ... print(p.id, p.author.username, p.body) ... 1 john my first post! # get all users in reverse alphabetical order >>> User.query.order_by(User.username.desc()).all() [<User susan>, <User john>] 

Flask-SQLAlchemy- , , .


, , , :


 >>> users = User.query.all() >>> for u in users: ... db.session.delete(u) ... >>> posts = Post.query.all() >>> for p in posts: ... db.session.delete(p) ... >>> db.session.commit() 

shell context


, , Python? , , :


 >>> from app import db >>> from app.models import User, Post 

, Python, . flask shell — . shell — "", flask , . - Python . これはどういう意味ですか 次の䟋を考えおみたしょう。


 (venv) $ python >>> app Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'app' is not defined >>> (venv) $ flask shell >>> app <Flask 'app'> 

app , , flask shell . flask shell , , , «shell context», .


microblog.py , :


 from app import app, db from app.models import User, Post @app.shell_context_processor def make_shell_context(): return {'db': db, 'User': User, 'Post': Post} 

app.shell_context_processor . flask shell , , . , , , , , , .


, flask shell , , :


 (venv) $ flask shell >>> db <SQLAlchemy engine=sqlite:////Users/migu7781/Documents/dev/flask/microblog2/app.db> >>> User <class 'app.models.User'> >>> Post <class 'app.models.Post'> 

<<<前 次>>>



Source: https://habr.com/ru/post/J346344/


All Articles