2012-06-07 3 views
1

Я разрабатываю веб-приложение, которое должно войти в базу данных с учетными данными, которые предоставляются конечным пользователем; само приложение не имеет входа в базу данных.Сериализовать подключение базы данных через сеанс

Проблема заключается в том, как создать одно соединение за пользовательская сессия.

Один подход: полномочия

  1. Запрос пользователя
  2. Проверьте учетные данные действительны на дб бэкэндом
  3. хранения учетных данных в сеансового уровня переменных

Проблема с этим подходом является, по каждому последующему запросу для этой сессии; вам нужно будет создать новое соединение; и это быстро исчерпает максимальные соединения с сервером.

Я использую Flask с Oracle.

В Flask находится объект g, в котором хранятся объекты с областью запроса. Этот фрагмент кода, хотя, не работает:

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

def login_required(f): 
    @wraps(f) 
    def decorated_function(*args, **kwargs): 
     if g.db is None: 
      return redirect(url_for('login', next=request.url)) 
     return f(*args, **kwargs) 
    return decorated_function 

class LoginForm(Form): 
    username = TextField('Username', [validators.Length(min=4, max=25)]) 
    password = PasswordField('Password', [validators.Required()]) 

@app.route('/app', methods=['GET','POST']) 
@login_required 
def index(): 
    return 'Index' 

@app.route('/', methods=['GET','POST']) 
def login(): 
    form = LoginForm(request.form) 
    if request.method == 'POST': 
     if form.validate(): 
      try: 
       dsn = cx_Oracle.makedsn(app.config['DB_HOST'], 
             app.config['DB_PORT'], app.config['DB_SID']) 
       g.db = cx_Oracle.connect(form.username.data, 
             form.password.data, dsn) 
      except cx_Oracle.DatabaseError as e: 
       flash(unicode(e), 'error') 
       return render_template('login.html', form=form) 
      return redirect(url_for('index')) 
     else: 
      return render_template('login.html', form=form) 
    else: 
     return render_template('login.html', form=form) 

AttributeError: '_RequestGlobals' object has no attribute 'db'

ответ

0

Похоже, вам необходимо реализовать пул соединений. Вместо того, чтобы запрашивать новое соединение для каждого запроса (которое вообще не масштабируется), вы просто проверяете соединение из пула с необходимыми атрибутами. Если подходящее соединение не доступно, пул создаст новый. Пул, конечно же, должен будет обрабатывать обратный случай при закрытии соединений, которые не использовались в течение некоторого времени.

Возможно, вы захотите проверить, доступен ли такой пул для python. Для java oracle это поддерживает UCP и OCI с пулом сеансов. Если я не ошибаюсь, пул соединений даже предоставляется для .Net.

+0

cx_Oracle обеспечивает объединение пулов, однако, чтобы инициировать пул, мне нужны учетные данные пользователя. Итак, как только я получаю пул, как я могу запросить подключения из этого пула в течение всего запроса? –

1

Причина, почему этот фрагмент кода не работает эта линия

if g.db is None: 

Вы обращаетесь к атрибуту, который не принадлежит г. Добавьте эти строки кода:

@app.before_request 
    def before_request(): 
     g.db = None 

Функции, отмеченные before_request() вызываются до запроса и не передается никаких аргументов.

Что касается соединения Pooling

Существует ОРМ и SQL Toolkit называется SQLAlchemy в Python, который делает соединение пулы автоматически. Он также управляет g-флагом и создает подготовленные операторы SQL, которые намного безопаснее.

Она состоит из двух частей:

1. Core which is a SQL abstraction toolkit. 
    2. ORM is an optional package which builds on top of Core. 

Так что, если вы не хотите использовать ORM затем просто использовать его ядро ​​со всеми функциями неповрежденными. Проверить here.

Он поддерживает Oracle через cx_Oracle и может быть настроен, как указано в документах SQLAlchemy Docs here.

Проверьте это question, чтобы узнать больше о пуле соединений в python.

Смежные вопросы