تعریف و دسترسی به دیتا بیس

این برنامه میخواهد از دیتا بیس SQLite انبار کردن کاربران و پست ها استفاده کند. پایتون با پشتیبانی داخلی از SQLite در ماژول sqlite3 آمده است.

SQLite راحت است زیرا هیچ الزامی برای راه‌اندازی جداگانه سرور ندارد و همچنین به صورت داخلی در پایتون قرار دارد. با این حال اگر چند درخواست همزمان بخواهند، به صورت همزمان در دیتا بیس داده بنویسند، سرعت بسیار کاهش میابد. البته این کاهش سرعت در برنامه های کوچک محسوس نیست. هنگامی که بزرگ شدید، شاید بخواهید از دیتا بیس دیگری استفاده کنید.

این آموزش درباره SQL نیست. اگر شما به این آشنا نیستید، مستندات SQLite در language شرح داده شده است.

اتصال به دیتابیس

اولین چیز این است که کجا با دیتا بیس SQLite (و سایر کتابخانه های دیتا بیس پایتون) یک اتصال بسازید؛ اکثر کوئری ها و عملیات ها در پلتفرم با استفاده از اتصال انجام میشوند و پس از اتمام کار بسته میشوند.

در برنامه های وب، این اتصال معمولا به درخواست مرتبط است. این اتصال در زمان رسیدگی به درخواست ایجاد میشود و قبل از ارسال پاسخ، بسته می شود.

flaskr/db.py
import sqlite3

import click
from flask import current_app, g


def get_db():
    if 'db' not in g:
        g.db = sqlite3.connect(
            current_app.config['DATABASE'],
            detect_types=sqlite3.PARSE_DECLTYPES
        )
        g.db.row_factory = sqlite3.Row

    return g.db


def close_db(e=None):
    db = g.pop('db', None)

    if db is not None:
        db.close()

g یک شی خاص است که برای هر درخواست، منحصر بفرد است. برای ذخیره داده هایی استفاده میشود که ممکن است توسط چندین تابع در طول درخواست قابل دسترسی باشد. اگر get_db برای بار دوم در آن درخواست، فراخوانی شود، به جای ایجاد یک اتصال جدید، اتصال ذخیره و دوباره استفاده می شود.

current_app یک شی خاص دیگر است که به برنامه فلاسک اشاره میکند تا درخواست را مدیریت کند. از آنجایی که شما از کارخانه برنامه کاربردی استفاده می‌کنید، هنگام نوشتن بقیه کد، شما هیچ شی دیگری برای برنامه نمیسازید. get_db زمانی فراخوانده می شود که برنامه ایجاد شود . در حال رسیدگی به درخواست باشد، بنابراین میتوان از current_app استفاده کرد.

sqlite3.connect() ارتباطی را با فایلی که توسط کلید پیکربندی که به`DATABASE`` اشاره شده است، برقرار میکند. این فایل هنوز لازم نیست وجود داشته باشد و تا زمانی که دیتابیس را بعدا مقداردهی نکنید، وجود نخواهد داشت.

sqlite3.Row به اتصال می گوید که ردیف هایی را که مانند دیکشنری ها رفتار می کنند، برگرداند. این اجازه می دهد تا به ستون ها با نام دسترسی داشته باشید.

close_db با بررسی اینکه g.db` تنظیم شده است، بررسی می‌کند که آیا یک اتصال ایجاد شده است. اگر اتصال وجود داشته باشد، بسته است. در ادامه به برنامه خود در مورد عملکرد close_db در کارخانه برنامه خواهید گفت تا پس از هر درخواست فراخوانی شود.

ساخته جدول ها

در SQLite، داده ها در tables و columns انبار میشوند. آنها نیاز دارند، قبل از انبار شدن و پس گرفتن داده ها، ساخته شوند. Flaskr میخواهد کاربران را در جدول user و پست ها را در جدول post انبار کند. یک فایل با دستور های SQL نیاز است تا جدول خالی ساخته شود. آن را بسازید:

flaskr/schema.sql
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS post;

CREATE TABLE user (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT UNIQUE NOT NULL,
  password TEXT NOT NULL
);

CREATE TABLE post (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  author_id INTEGER NOT NULL,
  created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  title TEXT NOT NULL,
  body TEXT NOT NULL,
  FOREIGN KEY (author_id) REFERENCES user (id)
);

و توابع پایتون دستورات SQL را در فایل db.py اجرا خواهند کرد:

flaskr/db.py
def init_db():
    db = get_db()

    with current_app.open_resource('schema.sql') as f:
        db.executescript(f.read().decode('utf8'))


@click.command('init-db')
def init_db_command():
    """Clear the existing data and create new tables."""
    init_db()
    click.echo('Initialized the database.')

open_resource() فایلی را نسبت به بسته flaskr باز می کند، که مفید است زیرا در زمان استقرار برنامه لزوماً نمی دانید آن مکان کجاست. get_db یک اتصال پایگاه داده را برمی گرداند که برای اجرای دستورات خوانده شده از فایل استفاده می شود.

click.command() یک خط فرمان به نام init-db را تعریف می کند که تابع init_db را فراخوانی می کند و پیام موفقیت آمیز را به کاربر نشان می دهد. برای کسب اطلاعات بیشتر در مورد نوشتن دستورات می توانید Command Line Interface را بخوانید.

ثبت نام با برنامه

توابع close_db و indit_db_command‍‍ باید در نمونه برنامه ثبت شوند. در غیر این صورت، آنها توسط برنامه استفاده نخواهند شد. با این حال، از آنجایی که شما از یک تابع کارخانه استفاده می کنید، این نمونه هنگام نوشتن توابع در دسترس نیست. در عوض، تابعی بنویسید که یک برنامه کاربردی را می گیرد و ثبت را انجام می دهد.

flaskr/db.py
def init_app(app):
    app.teardown_appcontext(close_db)
    app.cli.add_command(init_db_command)

app.teardown_appcontext() به فلاسک می گوید که هنگام پاکسازی پس از بازگرداندن پاسخ، آن تابع را فراخوانی کند.

app.cli.add_command() یک دستور جدید اضافه می کند که می تواند با دستور flask فراخوانی شود.

این تابع را از کارخانه وارد کرده و فراخوانی کنید. قبل از بازگرداندن برنامه، کد جدید را در انتهای عملکرد کارخانه قرار دهید.

flaskr/__init__.py
def create_app():
    app = ...
    # existing code omitted

    from . import db
    db.init_app(app)

    return app

راه اندازی فایل پایگاه داده

اکنون که init-db در برنامه ثبت شده است، می توان با استفاده از دستور flask، مشابه دستور run از صفحه قبل، آن را فراخوانی کرد.

توجه

If you're still running the server from the previous page, you can either stop the server, or run this command in a new terminal. If you use a new terminal, remember to change to your project directory and activate the env as described in نصب و راه‌اندازی.

دستور init-db را اجرا کنید:

$ flask --app flaskr init-db
Initialized the database.

اکنون فایل flaskr.sqlite در پوشه instance در پروژه خواهد بود.

با نقشه ها و نماها(Blueprints and Views) ادامه دهید.