古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。

Django全局变量和多环境配置:开发环境和生产环境区分

Python admin 675℃ 0评论

Django的日常开发部署中,我们经常会遇到需要在全局使用一个变量,同时也有开发环境和生产环境的配置不同的情况,如数据库主机地址差异等,通常在小项目或配置内容差别较少的情况下我们可以手动修改即可,但是随着项目配置内容逐渐增加、自动化构建需求等原因,我们还需要更加正规的部署手段,今天我们就来讲一下如何使用Django全局变量和区分开发、生产环境进行Django项目部署。

Django全局变量

WEB开发经常有的一个需求就是需要在所有的页面上面显示同样的后台数据,比如网站名称,虽然你可以硬编码,但是未免太过繁琐了,程序员还是要解放自己,这时候我们就要用到全局变量啦。当然这只是全局变量的用处之一,常说的Django的全局变量的概念就是可以在整个项目中使用的变量,一般存放在settings.py文件中,一处配置全局使用,可以极大的方便我们的开发。同时,将各种可能变化的配置信息统一管理,便于项目开发、扩展和变化。

举例说明全局变量的使用,在默认settings.py文件中:

需要注意的是,这里配置的全局变量都要使用大写!否则不会生效,使用会报错。

设置了全局变量后,使用方法很简单,首先需要在对应的视图函数模块文件中导入Django的配置信息:

然后在你的视图函数中就可以使用了:

如果想要在Django模板中使用全局变量,如刚刚我们设置的网站名称“SITE_NAME”这个变量,最终实现模板调用效果如下:

这样的目标有两种实现方法:

  • 每次在视图函数中获取全局变量传递到模板中;
  • 直接将要使用的全局变量注册到Django的模板系统中,模板会自动查找;

第一种方法,每次在视图函数view中render传递参数到模板中:

第二种方法是一劳永逸的方法,就是使用Django的模板系统“TEMPLATES ”,

首先我们需要建立一个视图函数,使模板可以调用这些配置信息:

然后我们需要将视图注册到Django模板系统TEMPLATES的上下文管理器中:

完成后就可以在各个模板文件中调用你已经配置的指定参数了。

Django多环境配置:开发、生产环境区分

OK,从刚刚的Django全局变量中你应该也可以发现了Django的配置信息都直接配置在了settings.py文件中,如果在生产和开发环境中配置信息不同,而我们又想要方便的进行区分, 举个例子,开发环境和生产环境一般数据库连接信息不一样 ,而我们只需要让Django找到对应环境的配置即可。

整体来看,这个区分配置正规的解决方案有三种:

  • 使用同一个settings.py配置文件,通过环境参数进行区分;
  • 使用不同的settings.py配置文件,运行时指定使用的配置;
  • 使用数据库等手段进行参数配置;

使用环境参数区分开发、生产环境

通过设置一个生产环境才有的环境变量,然后在settings.py中判断这个环境变量的存在与否来决定加载哪个环境的配置。 这里可以使用的环境参数很多,常用的有:

  • ENV
  • DJANGO_SETTINGS_MODULE
  • 其他自定义的参数;

以ENV为例,首先我们的settings.py文件还是只保留一份,可以参考下例编写内容:

有了这些内容,我们在运行项目的时候就可以进行区分,比如在生产环境中我们可以这样启动项目:

而在开发环境中:

在使用Jenkins等持续集成工具部署Django时,我们可以在构建环节直接设置环境变量,这样就可以保证使用django自带调试服务器和uwsgi一致的流程,如:

需要注意的是,

因为环境变量是进程级的,如果你在相同进程运行多个Django站点,这将不能正常工作。这在mod_wsgi中可能发生。为避免这个问题,使用mod_wsgi的守护模式,在各自的守护进程中运行各站点,或者通过在wsgi.py中强制设置os.environ[“DJANGO_SETTINGS_MODULE”] = “helloworld.settings”来覆盖环境变量值。

博主常用的配置内容如下:

加载不同的配置文件区分开发、生产环境

除了使用环境参数的方式,还可以给不同的开发环境提供不同的配置文件,运行时指明要加载的文件即可。

这种方法基本原理是使用了Django settings配置的懒加载原理,或者称为延时加载, 就是在需要用到的时候再加载。一般手段有代理类,线程。计时器。

当uWSGI服务器加载了你的应用,Django需要import其settings模块,其中定义了你的整个应用。Django使用DJANGO_SETTINGS_MODULE环境变量来定位合适的settings模块,它必须包含指向settings模块的点分开的路径(dotted path).
你可以在开发和生产环境使用不同的变量,这全取决于你如何组织你的配置。如果此变量未设置,默认的wsgi.py设置其为mysite.settings,mysite是你的项目。这就是runserver如何用默认的方式找到默认的settings的。

在Django项目的manage.py文件中,Django已经自动设置了读取的配置模块,当然这是可以修改的,manage.py在运行时还提供了–settings选项用于指定settings模块,默认内容参考如下:

采用uWSGI 之类的生产服务器部署时也需要用到uwsgi.py文件加载Django的配置文件,我们同样可以修改DJANGO_SETTINGS_MODULE,内容参考如下:

具体的方法就是提供settings参数来覆盖默认设置,如我们可以在项目原settings.py同级目录(也可以单独建立文件夹管理)新建两个配置文件,分别为settings_dev.py和settings_prod.py,并将各自环境的配置都配置好,这里不再做展示,大家心中有数,要做好区分即可。

文件目录结果如下:

有了不同环境的配置文件,在运行时就可以提供参数进行加载,如生产环境:

暴力点的同学,可以在项目启动的前,将对应环境的配置文件直接覆盖默认配置文件即可,然后什么烦恼都没有了。。。

当然有同学可能会对维护两个配置文件产生抵触,毕竟两个文件中也有很多内容是重复的,我们完全可以抽离出来复用,将相同的内容放在一个文件中,分别在开发和生产配置文件中引入即可。

还有的同学不是使用manage.py提供参数(类似runserver)来运行Django,可以使用下面这种方式:

使用数据库传递参数来区分开发、生产环境

常用的方式是使用redis,这种方式适合非项目启动参数和变动较少的常量数据,把参数通过后台编辑的方式(可以做一个管理页面)存到redis中。简单点的,可以每次都从redis获取配置,优化点的, 就是避免每次都从redis获取,用redis的发布订阅模式, 项目启动时把配置从redis中获取到缓存到本地内存中(如集合,常量等), 如果改动了redis数据, 项目订阅了此channel的消息, 然后从新从redis获取更新本机缓存,并且适合集群环境。

其他问题和建议

尽管Django提供了settings.configure的方式让我们可以修改全局配置变量,但是非常不建议你这样做,往往会有竞争冲突问题。同样的,考虑到Python的对象引用,在使用配置文件中的字典这种全局变量时,一定要使用深拷贝(copy.deepcopy())保证你传递的引用不会造成配置变更。

参考文献

转载请注明:北凉柿子 » Django全局变量和多环境配置:开发环境和生产环境区分

喜欢 (0)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址