2010-04-21 7 views
35

Я ищу простой, но рекомендуемый способ в Django для хранения переменной только в памяти. Когда Apache перезагружается или сервер разработки Django перезапускается, переменная сбрасывается обратно на 0. Более конкретно, я хочу подсчитать, сколько раз определенное действие происходит на каждом экземпляре модели (запись базы данных), но по соображениям производительности я не знаю, t хочет сохранить эти подсчеты в базе данных. Меня не волнует, исчезли ли счеты после перезапуска сервера. Но пока сервер работает, я хочу, чтобы эти подсчеты были согласованы между оболочкой Django и веб-интерфейсом, и я хочу иметь возможность вернуть, сколько раз действие было выполнено на каждом экземпляре модели.Python Django Глобальные переменные

Я не хочу, чтобы переменные были связаны с пользователем или сеансом, потому что я мог бы вернуть эти счеты без входа в систему (и я хочу, чтобы подсчеты были согласованы независимо от того, во что пользователь вошел в систему). Я описываю глобальную переменную? Если да, то как я могу использовать его в Django? Я заметил, что файлы, такие как urls.py, settings.py и models.py, по-видимому, анализируются только один раз для запуска сервера (в отличие от view.py, который, как представляется, обрабатывается временем eache, когда запрос выполняется). Означает ли это, что я должен объявить свои переменные в одном из этих файлов? Или я должен каким-то образом хранить его в атрибуте модели (если он работает до тех пор, пока сервер работает)? Это, наверное, простой вопрос, но я просто не уверен, как это делается в Django.

Любые комментарии или советы очень ценятся. Спасибо, Джо

+0

Кэширующие документы немного ориентированы на «кэширование». Перейти к «низкоуровневому» для получения подробной информации об использовании его для переменных сервера: https://docs.djangoproject.com/en/1.3/topics/cache/#the-low-level-cache-api –

+0

Это может вам помочь: [https://github.com/andres-torres-marroquin/django-system-globals](https://github.com/andres-torres-marroquin/django-system-globals) –

ответ

24

Вы не должны объявлять глобальные переменные. Настройки (константы) в порядке, если все сделано правильно. Но переменные нарушают архитектуру shared-nothing и могут вызвать массу проблем. (в лучшем случае они будут непоследовательными)

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

Новые incr() и decr() методы особенно подходят для подсчета. См. docs для получения дополнительной информации.

+3

+1 для их хранения в кэш. –

+0

Мне нравится этот подход, и я его реализую.В настоящее время я использую localmem для бэкэнда на сервере разработки Django и заметил, что подсчеты не сохраняются после просмотра нескольких веб-страниц на моем сайте. (В это время я НЕ перезапускал сервер разработки django). Я понимаю, что для этого может быть несколько причин. (В конце концов я буду использовать memcached). Просто интересно, если сервер разработки localmem cache/django не будет хранить кешированные значения долго или если у меня некорректная настройка конфигурации. –

+0

@Joe: Я всегда использую кеш-сервер в отсутствии надлежащего кэша, например memcached. Просто чтобы быть уверенным. Это происходит вместе с тем, «не беспокоясь о проблемах с производительностью, пока они не станут очевидными» и «измерьте перед оптимизацией». – muhuk

54

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

Вы можете объявить свой счетчик как модель класс -member. Затем, чтобы справиться с состоянием гонки, вам нужно добавить метод, который будет ждать, если какой-либо другой клиент из другого потока будет работать со счетчиком. Что-то вроде этого:

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, никаких действий не требуется.

+1

Это именно то, что я хочу. Мне нужно создать серийный идентификатор, который будет увеличен для каждого запроса для целей тестирования. В реальной системе идентификатор поступает из внешнего API. – k4ml

+2

Это может быть жизнеспособным подходом для игрушечных проектов. Но как только вы начнете использовать этот класс, вы гарантируете, что ваше приложение не масштабируется. Существует причина, по которой у нас есть подсистема кеша. – muhuk

+1

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

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