Python Django全局变量
我想在Django中找到一种简单但推荐的方法来只在内存中存储一个变量。当Apache重启或Django开发服务器重启时,这个变量会重置为0。更具体地说,我想统计每个模型实例(数据库记录)上某个特定操作发生的次数,但出于性能考虑,我不想把这些计数存储在数据库里。我不在乎这些计数在服务器重启后消失。只要服务器在运行,我希望这些计数在Django命令行和网页界面之间保持一致,并且我希望能够返回每个模型实例上这个操作发生了多少次。
我不想让这些变量和用户或会话关联,因为我可能想在未登录的情况下返回这些计数(而且我希望这些计数在任何用户登录时都保持一致)。我是在描述一个全局变量吗?如果是的话,我该如何在Django中使用它?我注意到像urls.py、settings.py和models.py这样的文件似乎在服务器启动时只解析一次(而views.py似乎每次请求时都会解析)。这是否意味着我应该在这些文件中的一个地方声明我的变量?还是应该以某种方式将它存储在模型属性中(只要它在服务器运行期间保持有效)?这可能是个简单的问题,但我不太确定在Django中该怎么做。
任何评论或建议都非常感谢。
谢谢,
乔
6 个回答
我会在根目录下创建一个叫“config.py”的文件,然后把所有的全局变量放在里面:
x = 10
my_string = ''
在“view.py”文件中:
from your_project import config
def MyClass(reuqest):
y = config.x + 20
my_title = config.my_string
...
这样做的好处是,这些变量可以在多个.py文件之间共享,而且管理起来也很方便。
为什么不应该声明全局变量呢?这听起来有点像宣传。如果作者知道自己想要什么,并且清楚会有什么副作用,那为什么不呢?也许这只是一个快速的实验。
你可以把计数器声明为一个模型的类成员。为了处理竞争条件,你需要添加一个方法,这个方法会在其他线程的客户端正在使用计数器时等待。大概是这样的:
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
,那就不需要做任何额外的操作。
你不应该声明全局变量。如果是设置(常量),那可以,但要正确使用。变量会和无共享架构相冲突,可能会引发很多麻烦。(最好的情况是它们会变得不一致)
我建议把这些统计数据存储在缓存中。(其实我会把它们存到数据库里,但你已经明确表示你认为这样会对性能产生负面影响,所以……)
新的incr()
和decr()
方法特别适合用来计数。想了解更多信息,可以查看文档。