2015-05-17 4 views
1

Предположим, у меня есть класс, в котором хранятся важные динамические данные, которые мне нужны для рендеринга моих сайтов. Этот класс должен быть создан индивидуально для каждого пользователя, а данные из класса должны обновляться в соответствии с некоторым пользовательским вводом, так что, по крайней мере, две точки зрения:Доступ к экземплярам класса в нескольких флягах?

@app.route('/') 
def index(): 
    myclass = MyClass() 
    return render_template('index.html') 

@app.route('/_update', methods=['GET']) 
def update(): 
    ret_data = {"value": request.args.get('c', type=float)} 
    a = myclass.calculate(ret_data['value']) 
    return jsonify(result=a) 

Ofcourse он не может работать таким образом, потому что myclass не существовало бы в update() - поэтому рабочим решением было бы сделать myclass глобальным при создании. Но это не кажется чистым, и это разрушает возможность отдельных классов за сеанс.

Итак, есть ли какой-либо чистый способ доступа к экземпляру класса в разных представлениях, или как мне с этим справиться, это не похоже на необычный сценарий для меня.

Во-вторых, я хотел бы, чтобы экземпляр класса был создан для каждого пользователя, но также закрыт, когда каждый пользователь закрывает окно своего браузера и т. Д. - Я действительно не понимаю, как это сделать, у меня есть функция __del__() мой класс, но он не будет использоваться, если я установил экземпляр в глобальный.

спасибо!

ответ

3

У вас есть фундаментальное непонимание того, как работают веб-приложения. Они stateless: ничто не используется между запросами для любого конкретного пользователя. Напротив, любая глобальная переменная будет доступна любому пользователю, попавшему в приложение далее.

Способ сохранения состояния для пользователя заключается в его размещении в базе данных. Вы можете использовать cookie сеанса, чтобы связать отдельного пользователя с их конкретными данными.

+0

Спасибо, вы абсолютно правы, я пока мало знаю о веб-приложениях. Позвольте мне попытаться объяснить немного больше моей проблемы: класс занимает много времени, чтобы начать (допустим, 20 секунд) - поэтому он должен запускаться только один раз для пользователя, например. после того, как он нажал кнопку «Старт».Впоследствии экземпляр класса по-прежнему необходим, поскольку он выполняет некоторые вычисления в зависимости от ввода пользователя и отправки новых данных клиенту (на самом деле клиент запрашивает данные), но поскольку классу требуется много памяти, он должен закрываться, когда пользователь уходит/выходит в течение некоторого времени. – lakerz

+0

Я не вижу прямо сейчас, как база данных может это решить - поскольку мой класс уже ведет себя (наивно думает), как база данных. Я имею в виду, что я мог хранить исходные данные класса в базе данных, но что, когда вызывается 'update()'? Мне нужно обновить данные базы данных точно из одного экземпляра класса. – lakerz

+0

Дело в том, что между пользователем и внутренним процессом нет постоянной связи. Поэтому, даже если вы создавали экземпляр своего класса по первому запросу для пользователя, следующий запрос от этого пользователя, вероятно, не перейдет к одному и тому же процессу; и следующий запрос к этому процессу, вероятно, будет от отдельного пользователя. Единственный способ сделать что-то вроде этого - использовать длительные соединения (например, Websockets), что является совершенно другим способом написания приложений. –

0

Как отметил Даниэль Роземанн, это, вероятно, не то, как нужно проектировать веб-приложение. Тем не менее, есть возможность достичь этой функциональности, используя глобальные переменные плюс несколько экземпляров. Я не знаю достаточно о python, чтобы оценить, насколько неверно (или даже опасно) использование глобальных переменных, но, похоже, работает для меня - я рад каждому комментарию по этому решению:

Установка двух глобальных диктонов , один для хранения экземпляров класса, один для уследить, если экземпляр по-прежнему актуален:

global session_instances, session_alive 
session_instances = {} 
session_alive = {} 

в моем корневом зрении создать UUID и сохранить экземпляр класса с ним в Словаре и запустить поток, который должен закрыть мой класс через некоторое время:

@app.route('/') 
def index(): 
    if not session.get('uid'): 
     session['uid'] = uuid.uuid4() 
     session_instances.update({session['uid'] : pyd2d.d2d()}) 
     session_alive.update({session['uid'] : 0}) 
     t = Thread(target=close_session, args = (session['uid'],)) 
     t.start() 
    return render_template('index.html') 

T он отвечает за закрытие (например, 15 секунд после последнего запроса):

def close_session(uid): 
    global session_alive 
    while True: 
     time.sleep(15) 
     if session_alive[uid] == 0: 
      session_instances[uid].stop() 
      break 
     session_alive[uid] = 0 

И, наконец, обновить в любое время таймера запрос высылается:

@app.before_request 
def before_request(): 
    global session_alive 
    if session.get('uid'): 
     session_alive[session['uid']] = 1 

Это, кажется, работает нормально. Должен ли я плохо относиться к использованию глобальных переменных, или это нормально в таких случаях? Я ценю любой вклад!

+0

Хм, этот код отлично работает даже без трех «глобальных» линий - интересно, почему? Поскольку глобальные переменные определены снаружи, я могу получить к ним доступ, не устанавливая их в «global», но я думал, что мне не разрешено изменять их внутри функции (как в before_request) без использования «global ...»? – lakerz

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