2010-10-28 68 views
14

我想在Django Projects中有一些常量。例如,我们假设一个叫做MIN_TIME_TEST的常量。在Django中定义常量

我希望能够访问这个常量在两个地方:从我的Python代码内,并从任何模板内。

要做到这一点,最好的方法是什么?

编辑: 为了澄清,我知道模板上下文处理器,只是把东西放在settings.py或其他文件,只是导入。

我的问题是,如何合并不违反“不重复自己”的两种办法治?基于迄今为止的答案,这里是我的方法:

我想创建一个名为global_constants.py的文件,它将有一个常量列表(例如MIN_TIME_TEST = 5)。我可以将import这个文件放到任何模块中去获取常量。

但现在,我想创建背景处理器返回所有这些常量。我怎么能自动地做这件事,而不必像字典中那样再次列出它们,就像John Mee的回答一样?

回答

14

两个Luper和弗拉基米尔是正确的,但恕我直言,你需要这既是为了完成你的要求。

  • 虽然参数并不需要是在settings.py,你可以把他们的任何地方,从地方将其导入到你的视图/模型/模块代码。如果我不介意将它们视为全球相关,我有时会将它们放入__init__.py

  • 这样的背景处理器将确保选择的变量是全局在模板范围

    def settings(request): 
        """ 
        Put selected settings variables into the default template context 
        """ 
        from django.conf import settings 
        return { 
         'DOMAIN':  settings.DOMAIN, 
         'GOOGLEMAPS_API_KEY': settings.GOOGLEMAPS_API_KEY, 
        } 
    

但如果你是新来的Django这可能是矫枉过正;也许你只是问如何将变量放入模板范围......?

from django.conf import settings 

... 
# do stuff with settings.MIN_TIME_TEST as you wish 

render_to_response("the_template.html", { 
    "MIN_TIME_TEST": settings.MIN_TIME_TEST 
}, context_instance=RequestContext(request) 
+0

谢谢,这的确是我想去的方向。但请看我的澄清/其他问题,即我怎么能做你说的,而不必两次列出所有的常量? – 2010-10-28 14:26:04

+0

将它们全部包装成字典,然后将该字典放入上下文中。您将通过点符号访问它们。例如:{{yourDict.yourConstant}} – 2010-10-28 23:36:41

3

考虑把它变成你的应用程序的settings.py。当然,为了在模板中使用它,您需要将其作为任何其他常用变量提供给模板。

2

使用context processors到在所有可用模板的常数(settings.py是一个很好的地方,它们定义为弗拉基米尔说的)。

+0

什么将它们添加到背景处理器settings.py中定义它们后的好办法?我宁愿不必重复所有常量的名称。 – 2010-10-28 11:42:08

+0

所有的信息都可以在页面上找到Luper Rouch链接。你将不得不创建一个python函数,它将返回一个变量字典(这是你返回常量的地方),并在TEMPLATE_CONTEXT_PROCESSORS设置中列出你的函数。 – 2010-10-28 11:46:11

0

你可以使用类似的背景处理器:

import settings 

context = {} 
for item in dir(settings): 
    #use some way to exclude __doc__, __name__, etc.. 
    if item[0:2] != '__': 
     context[item] = getattr(settings, item) 
4

要建立在别人的答案,这里是你实现这个简单的方法:

在你的设置文件:

GLOBAL_SETTINGS = { 
    'MIN_TIME_TEST': 'blah', 
    'RANDOM_GLOBAL_VAR': 'blah', 
} 

然后,构建关中John Mee's context processor

def settings(request): 
    """ 
    Put selected settings variables into the default template context 
    """ 
    from django.conf import settings 
    return settings.GLOBAL_SETTINGS 

这将解决DRY问题。

或者,如果你只打算偶尔使用全局设置,并希望从视图中称他们为:在同样的想法乔丹瑞特

def view_func(request): 
    from django.conf import settings 
    # function code here 
    ctx = {} #context variables here 
    ctx.update(settings.GLOBAL_SETTINGS) 
    # whatever output you want here 
0

约翰眉的最后一部分变,有一点阐述讨论。

假设你有你的设置类似于乔丹什么东西建议 - 换句话说,是这样的:

GLOBAL_SETTINGS = { 
    'SOME_CONST': 'thingy', 
    'SOME_OTHER_CONST': 'other_thingy', 
} 

进一步假设已经有了一些变量的字典你,你想传递您的模板,可能作为参数传递给您的视图。我们称之为my_dict。假设您希望my_dict中的值覆盖settings.GLOBAL_SETTINGS字典中的值。

你可能会做一些在你看来这样的:

def my_view(request, *args, **kwargs) 
    from django.conf import settings 
    my_dict = some_kind_of_arg_parsing(*args,**kwargs) 
    tmp = settings.GLOBAL_SETTINGS.copy() 
    tmp.update(my_dict) 
    my_dict = tmp 
    render_to_response('the_template.html', my_dict, context_instance=RequestContext(request)) 

这可让您在全球拥有确定的设置,提供给您的模板,不需要你手动输入了他们每个人。

如果有任何额外的变量传递模板,也没有任何需要重写,你可以做:

render_to_response('the_template.html', settings.GLOBAL_SETTINGS, context_instance=RequestContext(request)) 

什么,我在这里讨论&之间的主要区别是什么乔丹有,对他来说,settings.GLOBAL_SETTINGS覆盖了它可能与你的上下文字典有共同之处,而在我的情况下,我的上下文字典覆盖了settings.GLOBAL_SETTINGS。因人而异。

1

上下文处理器更适合处理更多动态对象数据 - 它们被定义为documentation中的映射,在许多帖子中它们被修改或传递给视图 - 它不会理解模板可能会失去对全局信息的访问,例如,您忘记在视图中使用专用的上下文处理器。数据全球定义为&,将视图耦合到模板。

更好的方法是定义一个自定义模板标签。通过这种方式:

  • 模板不靠看法已经全球信息传递到他们
  • 它的DRY-ER:定义全局设置的应用程序可以出口到很多项目,跨项目
  • 消除公共代码
  • 模板决定他们是否有机会获得全球信息,而不是视图功能

在下面的例子中我解决你的问题 - 在这个MIN_TIME_TEST可变载荷 - 和我经常要面对的问题,在装在我的环境c时更改的URL hanges。

我有4个环境 - 2开发和生产2:

  • 开发:Django的Web服务器,网址:本地主机:8000
  • 开发:Apache Web服务器:网址:sandbox.com - >解析为127.0.0.1
  • PROD沙盒服务器,网址:sandbox.domain.com
  • PROD服务器:网址:domain.com

我这样做对我的所有项目&将所有的url保存在一个文件global_settings.py中,以便从代码访问它。我定义了可以(可选)加载到任何模板的自定义模板标记{%site_url%}

我创建了一个名为global_settings的应用程序,并确保它包含在我的settings.INSTALLED_APPS元组中。

Django的模板编译成文字以告诉数据应该如何显示渲染()方法节点 - 我创建了一个基于传入的名字在我的global_settings.py returnning值呈现数据的对象

它看起来像这样:现在

from django import template 
import global_settings 

class GlobalSettingNode(template.Node): 
    def __init__(self, settingname): 
     self.settingname = settingname; 
    def render(self, context): 
     if hasattr(global_settings, self.settingname): 
      return getattr(global_settings, self.settingname) 
     else: 
      raise template.TemplateSyntaxError('%s tag does not exist' % self.settingname) 

,在global_settings.py我注册了几个标签:SITE_URL我的例子和min_test_time您的例子。这样,当从模板调用{%min_time_test%}时,它会调用get_min_time_test,它解析为加载值= 5。在我的示例中,{%site_url%}将执行基于名称的查找,以便我可以一次定义全部4个URL并选择使用的环境。这对我来说比使用Django的内置设置更灵活.Debug = True/False标志。

from django import template 
from templatenodes import GlobalSettingNode 
register = template.Library() 


MIN_TIME_TEST = 5 

DEV_DJANGO_SITE_URL = 'http://localhost:8000/' 
DEV_APACHE_SITE_URL = 'http://sandbox.com/' 
PROD_SANDBOX_URL = 'http://sandbox.domain.com/' 
PROD_URL = 'http://domain.com/' 

CURRENT_ENVIRONMENT = 'DEV_DJANGO_SITE_URL' 



def get_site_url(parser, token): 
    return GlobalSettingNode(CURRENT_ENVIRONMENT) 

def get_min_time_test(parser, token): 
    return GlobalSettingNode('MIN_TIME_TEST') 

register.tag('site_url', get_site_url) 
register.tag('min_time_test', get_min_time_test) 

注意,对于这项工作,Django是期待global_settings.py将设在你的Django应用下包装称为templatetags蟒蛇。我在这里的Django的应用程序被称为global_settings,所以我的目录结构如下:

/project-name/global_settings/templatetags/global_settings.py 等

最后的模板选择在全局设置与否是否加载,这对性能有益。将此行添加到您的模板中以公开在global_settings中注册的所有标记。潘岳:

{% load global_settings %} 

现在,需要MIN_TIME_TEST或这些环境暴露只需安装此应用等项目=)