代码之家  ›  专栏  ›  技术社区  ›  Edan Maor

在Django中定义常量

  •  18
  • Edan Maor  · 技术社区  · 15 年前

    MIN_TIME_TEST .

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

    做这个最好的方法是什么?

    为了澄清这一点,我了解模板上下文处理程序,也知道只需将内容放入settings.py或其他文件,然后只需导入即可。

    我的问题是,如何在不违反“不重复自己”规则的情况下将这两种方法结合起来?根据目前的答案,我的方法是:

    我想创建一个名为global_constants.py的文件,它将有一个常量列表(比如 MIN_TIME_TEST = 5 ). 我可以 import 此文件进入任何模块以获取常量。

    但现在,我想创建一个上下文处理器,它返回所有这些常量。我怎么能不必再像约翰·米的答案那样,把它们列在字典里,就自动地完成这项工作呢?

    7 回复  |  直到 15 年前
        1
  •  17
  •   John Mee    15 年前

    卢珀和弗拉基米尔都是正确的imho,但你需要两者来完成你的要求。

    • 不过,常数不是 需要 __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)
    
        2
  •  6
  •   Community Mohan Dere    9 年前

    为了建立在别人的答案之上,这里有一个简单的实现方法:

    在设置文件中:

    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
    

    这将解决干燥的问题。

    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
    
        3
  •  3
  •   devmiles.com    15 年前

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

        4
  •  2
  •   Luper Rouch François Lagunas    15 年前
        5
  •  2
  •   Alan Illing    14 年前

    上下文处理器更适合处理更动态的对象数据——它们被定义为 documentation 在这里的许多文章中,它们被修改或传递给视图——模板可能失去对全局信息的访问是没有意义的,因为,例如,您忘记在视图中使用专门的上下文处理器。根据将视图与模板耦合的定义,数据是全局的。

    • 模板不依赖于视图来传递全局信息
    • 模板决定它们是否可以访问全局信息,而不是视图函数

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

    • Dev:django web服务器,url:localhost:8000
    • Dev:apache web服务器:url:sandbox.com->解析为127.0.0.1
    • 产品服务器:url:domain.com

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

    我创建了一个名为global_settings的应用程序,并确保它包含在我的设置中。INSTALLED_app s tuple。

    Django使用render()方法将模板文本编译成节点,该方法告诉数据应该如何显示——我创建了一个对象,该对象根据传入的名称返回global_settings.py中的值来呈现数据。

    看起来是这样的:

    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)
    

    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的python包中。我在这里的Django应用程序称为全局设置,因此我的目录结构如下:

    /项目名称/global_settings/templatetags/global_settings.py

    最后,模板选择是否在全局设置中加载,这有利于提高性能。将此行添加到模板以公开在global_settings.py中注册的所有标记:

    {% load global_settings %}
    

    现在,其他需要最少时间测试的项目或这些公开的环境只需安装此应用程序即可)

        6
  •  0
  •   andrei1089    15 年前

    在上下文处理器中,您可以使用以下内容:

    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)
    
        7
  •  0
  •   desfido    15 年前

    假设您的设置中有类似于Jordan建议的内容,换句话说,类似于:

    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))
    

    我在这里讨论的和乔丹的主要区别在于, 设置.全局设置 重写它与上下文词典的任何共同点,而与我的上下文词典一起重写 设置.全局设置 . YMMV公司。