Flask, управление соединениями с БД (без ORM) - PullRequest
1 голос
/ 18 апреля 2019

Я новичок в Flask и веб-программировании в целом, поэтому я пытаюсь понять принципы контекстов и операций с базами данных в рамках. Теперь я хочу разобраться, как управлять соединениями с БД без Sql-Alchemy и других ORM, просто с простым sql.

Итак, простой пример с sqlite3 db. Структура моего тестового проекта:

.
├── application
│   ├── __init__.py
│   ├── routes.py
│   └── templates
│       ├── base.html
│       ├── index.html
├── config.py
├── requirements.txt
├── run.py
└── test.db

* 1007 INIT * .py

from flask import Flask,g
from config import Config
import sqlite3

app = Flask(__name__)
app.config.from_object(Config)


def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect('test.db')
    return db

@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.close()

from application import routes

routes.py

# -*- coding: utf-8 -*-
from flask import render_template,redirect
from application import app, get_db
# import sqlite3


@app.route('/')
def index():
    cur = get_db().cursor()
    cur.execute('select*from users')
    select=cur.fetchall()
    return render_template('index.html',title='DBSelectTest', posts=select)

Я скопировал функции "get_db" и "close_connection" с официального сайта фреймворка Flask, но я не совсем понимаю, как это работает и в чем будет разница, если я использую простой код для "def get_db" без "г", как это:

con = sqlite3.connect("catalog.db")
cur = con.cursor() 

И, очевидно, закрывать соединения после выполнения запроса так:

cur.close()    
con.close() 

Я просто пытаюсь понять, как в этом случае работают контексты приложения и запроса с использованием g. Основная проблема в том, что я не понимаю, что такое «запрос» в таком случае.

Мое неправильное понимание этого дела:

Таким образом, в init .py мы создаем «глобальную переменную» g, которая находится в контексте приложения и должна быть доступна для каждого шага в контексте запроса. В rout.py мы получаем запрос от клиента с корневым маршрутом ("/"), поэтому в этот момент создается контекст запроса и после этого контекста приложения. Итак, насколько я понимаю, «get_db» доступен из контекста нашего запроса, и мы можем подключиться к базе данных и использовать это значение g во всех функциях внутри текущего шага? Что насчет "close_connection"? Из-за декоратора teardown_appcontext соединения должны быть закрыты после сбоя или завершения контекста приложения? Будет ли это работать в моем коде?

Итак, кто-нибудь может представить правильный случай использования простого sql с отдельной функцией подключения?

1 Ответ

1 голос
/ 19 апреля 2019

Контексты приложения и запроса Flask ведут себя как глобальные переменные для целей вашего кода, но на самом деле являются прокси-серверами, которые будут содержать разные значения каждый раз, когда ваше приложение получает новый веб-запрос.Контекст запроса содержит данные, относящиеся к этому конкретному веб-запросу, такие как данные формы, удаленный IP-адрес, http-заголовки и т. Д. Каждый раз, когда веб-запрос получен, новые контексты приложения и запроса создаются перед вызовом функции представления, а затемуничтожен после того, как ответ был возвращен и обработка веб-запроса была завершена.Данный прокси-сервер хранится в контексте приложения и используется для хранения переменных со временем жизни этого конкретного веб-запроса.Это используется для передачи информации между функциями, вызываемыми колбой в результате событий и сигналов.В своем коде вы используете декоратор, чтобы зарегистрировать функцию close_connection с событием teardown_appcontext, гарантируя, что она вызывается после завершения обработки каждого веб-запроса.Существует множество других событий, которые можно подключить для выполнения до или после функции просмотра, чтобы обеспечить предварительную и последующую обработку запроса или ответа.Прокси-сервер g просто используется для хранения вашего соединения с базой данных, которое было создано в вашей функции просмотра, и делает его доступным для функции close_connection, где он гарантированно будет закрыт.Это предотвращает открытое соединение с базой данных, если в коде вашего приложения произошла ошибка.Этот шаблон используется для достижения того же результата, что и при использовании диспетчера контекста (или попытки, кроме блока finally), чтобы закрыть соединение с базой данных в вашей функции.Этот шаблон обычно используется с ORM, чтобы скрыть основное управление соединением с базой данных и уменьшить стандартный код.Следующий код должен давать тот же эффект без использования событий или данного прокси.

# -*- coding: utf-8 -*-
from flask import render_template,redirect
from application import app
from contextlib import closing
import sqlite3

def get_db():
    return sqlite3.connect('test.db')

@app.route('/')
def index():
    with closing(get_db()) as conn:
        cur = conn.cursor()
        cur.execute('select*from users')
        select=cur.fetchall()
    return render_template('index.html',title='DBSelectTest', posts=select)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...