Глобальные переменные Python Django
Я ищу простой, но рекомендуемый способ в Django для хранения переменной только в памяти. Когда перезапускается Apache или сервер разработки Django, переменная reset возвращается к 0. Более конкретно, я хочу подсчитать, сколько раз определенное действие происходит на каждом экземпляре модели (запись базы данных), но по соображениям производительности я не хотите хранить эти подсчеты в базе данных. Меня не волнует, исчезли ли счеты после перезапуска сервера. Но пока сервер работает, я хочу, чтобы эти подсчеты были согласованы между оболочкой Django и веб-интерфейсом, и я хочу иметь возможность вернуть, сколько раз действие было выполнено на каждом экземпляре модели.
Я не хочу, чтобы переменные были связаны с пользователем или сеансом, потому что я мог бы захотеть вернуть эти счеты без входа в систему (и я хочу, чтобы подсчеты были согласованы независимо от того, какой пользователь входит в систему). Я описываю глобальную переменную? Если да, то как я могу использовать его в Django? Я заметил, что файлы, такие как urls.py, settings.py и models.py, по-видимому, анализируются только один раз для запуска сервера (в отличие от view.py, который, как представляется, обрабатывается временем eache, когда запрос выполняется). Означает ли это, что я должен объявить свои переменные в одном из этих файлов? Или мне следует каким-то образом сохранить его в атрибуте модели (если он работает до тех пор, пока сервер работает)? Это, наверное, простой вопрос, но я просто не уверен, как это делается в Django.
Любые комментарии или советы очень ценятся.
Благодаря,
Джо
Ответы
Ответ 1
Вы не должны объявлять глобальные переменные. Настройки (константы) в порядке, если все сделано правильно. Но переменные нарушают архитектуру без общего доступа и могут вызвать множество проблем. (в лучшем случае они будут непоследовательными)
Я бы просто сохранил эту статистику в кеше. (Хорошо, я бы сохранил их в базе данных, но вы поняли, что считаете, что это окажет негативное влияние на производительность, поэтому...)
Новые методы incr()
и decr()
особенно подходят для подсчета. Подробнее см. docs.
Ответ 2
Почему один не должен объявлять глобальные переменные? O_o. Это просто похоже на пропаганду. Если автор знает, чего он хочет и какие побочные эффекты будут, почему бы и нет. Может быть, это просто быстрый эксперимент.
Вы можете объявить свой счетчик в качестве члена класса модели. Затем, чтобы справиться с состоянием гонки, вам нужно добавить метод, который будет ждать, если какой-либо другой клиент из другого потока будет работать со счетчиком. Что-то вроде этого:
import threading
class MyModel(ModelBase):
_counter = 0
_counter_lock = threading.Lock()
@classmethod
def increment_counter(cls):
with cls._counter_lock:
cls._counter += 1
def some_action(self):
# core code
self.increment_counter()
# somewhere else
print MyModel._counter
Помните, однако, что вы должны иметь свое приложение в одном процессе. Поэтому, если вы развернули приложение под Apache, убедитесь, что он настроен на создание множества потоков, но не много процессов. Если вы экспериментируете с ./manage.py run
, никаких действий не требуется.
Ответ 3
Если вы хотите избежать хлопот с базой данных Django, например, проблемы миграции или производительности, вы можете рассмотреть базу данных в памяти redis. Redis гарантирует согласованность, даже если есть несколько процессов Django.