在 Django 中定义常量
我想在 Django 项目中有一些常量。例如,假设有一个名为 MIN_TIME_TEST
的常量。
我希望能够在两个地方访问这个常量:从我的 Python 代码中,以及从任何模板中。
执行此操作的最佳方法是什么?
编辑: 为了澄清这一点,我了解模板上下文处理器以及将内容放入 settings.py 或其他文件中然后导入。
我的问题是,如何结合这两种方法而不违反“不要重复自己”规则?根据到目前为止的答案,这是我的方法:
我想创建一个名为 global_constants.py 的文件,其中包含常量列表(例如 MIN_TIME_TEST = 5
)。我可以将此文件导入到任何模块中以获取常量。
但现在,我想创建返回所有这些常量的上下文处理器。我怎样才能自动执行此操作,而不必像 John Mee 的回答那样在字典中再次列出它们?
I want to have some constants in a Django Projects. For example, let's say a constant called MIN_TIME_TEST
.
I would like to be able to access this constant in two places: from within my Python code, and from within any Templates.
What's the best way to go about doing this?
EDIT:
To clarify, I know about Template Context Processors and about just putting things in settings.py or some other file and just importing.
My question is, how do I combine the two approaches without violating the "Don't Repeat Yourself" rule? Based on the answers so far, here's my approach:
I'd like to create a file called global_constants.py, which will have a list of constants (things like MIN_TIME_TEST = 5
). I can import
this file into any module to get the constants.
But now, I want to create the context processor which returns all of these constants. How can I go about doing this automatically, without having to list them again in a dictionary, like in John Mee's answer?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
恕我直言,卢珀和弗拉基米尔都是正确的,但你需要两者才能完成你的要求。
虽然,常量不需要位于 settings.py 中,但您可以将它们放在任何位置并将它们从该位置导入到视图/模型/模块代码中。如果我不想让它们被认为是全局相关的,我有时会将它们放入
__init__.py
中。像这样的上下文处理器将确保所选变量全局位于模板范围内
但是如果您是 django 的新手,这可能有点过分了;也许您只是问如何将变量放入模板范围......?
Both Luper and Vladimir are correct imho but you'll need both in order to complete your requirements.
Although, the constants don't need to be in the settings.py, you could put them anywhere and import them from that place into your view/model/module code. I sometimes put them into the
__init__.py
if I don't care to have them to be considered globally relevant.a context processor like this will ensure that selected variables are globally in the template scope
But this might be overkill if you're new to django; perhaps you're just asking how to put variables into the template scope...?
为了以其他人的答案为基础,您可以通过以下简单的方法来实现:
在您的设置文件中:
然后,构建 John Mee 的上下文处理器:
这将解决 DRY 问题。
或者,如果您只打算偶尔使用全局设置并希望从视图中调用它们:
To build on other people's answers, here's a simple way you'd implement this:
In your settings file:
Then, building off of John Mee's context processor:
This will resolve the DRY issue.
Or, if you only plan to use the global settings occasionally and want to call them from within the view:
考虑将其放入应用程序的 settings.py 中。当然,为了在模板中使用它,您需要将其像任何其他常用变量一样可供模板使用。
Consider putting it into settings.py of your application. Of course, in order to use it in template you will need to make it available to template as any other usual variable.
使用上下文处理器来让你的常量在所有模板中可用(settings.py 是定义它们的好地方,正如弗拉基米尔所说)。
Use context processors to have your constants available in all templates (settings.py is a nice place to define them as Vladimir said).
上下文处理器更适合处理更动态的对象数据——它们被定义为 文档,并且在此处的许多帖子中,它们都被修改或传递给视图 - 模板可能会失去对全局信息的访问,因为例如您忘记了,这是没有意义的在视图中使用专门的上下文处理器。根据定义,数据是全球性的将视图与模板结合起来。
更好的方法是定义自定义模板标签。这样:
在下面的例子中,我处理了你的问题——加载到这个 MIN_TIME_TEST 变量中——以及我经常遇到的问题,加载到当我的环境改变时会改变的 URL。
我有 4 个环境 - 2 个开发环境和 2 个生产环境:
我在所有项目上都执行此操作将所有网址保存在文件 global_settings.py 中,以便可以通过代码访问。我定义了一个自定义模板标签 {% site_url %} ,可以(可选)加载到
我创建的名为 global_settings 的应用程序的任何模板中,并确保它包含在我的 settings.INSTALLED_APPS 元组中。
Django 使用 render() 方法将模板化文本编译到节点中,该方法告诉如何显示数据 - 我创建了一个对象,该对象通过根据传入的名称返回 global_settings.py 中的值来呈现数据。
它看起来像这样
: ,在 global_settings.py 中,我注册了几个标签:我的示例的 site_url 和您的示例的 min_test_time 。这样,当从模板调用 {% min_time_test %} 时,它将调用 get_min_time_test ,它解析为加载 value=5。在我的示例中,{% site_url %} 将执行基于名称的查找,以便我可以同时定义所有 4 个 URL 并选择我正在使用的环境。这对我来说比仅仅使用 Django 内置的 settings.Debug=True/False 标志更灵活。
请注意,为了使其正常工作,django 期望 global_settings.py 位于 Django 应用程序下名为 templatetags 的 python 打包中。我的 Django 应用程序称为 global_settings,因此我的目录结构如下所示:
/project-name/global_settings/templatetags/global_settings.py
等等。
最后模板选择是否在全局设置中加载,这有利于性能。将此行添加到您的模板中以公开在 global_settings.py 中注册的所有标记:
现在,需要 MIN_TIME_TEST 或公开的这些环境的其他项目可以简单地安装此应用程序 =)
Context processors are better suited at handling more dynamic object data--they're defined as a mapping in the documentation and in many of the posts here they're being modified or passed around to views--it doesn't make sense that a template may lose access to global information because, for example, your forgot to use a specialized context processor in the view. The data is global by definition & that couples the view to the template.
A better way is to define a custom template tag. This way:
In the example below I deal with your problem--loading in this MIN_TIME_TEST variable--and a problem I commonly face, loading in URLs that change when my environment changes.
I have 4 environments--2 dev and 2 production:
I do this on all my projects & keep all the urls in a file, global_settings.py so it's accessible from code. I define a custom template tag {% site_url %} that can be (optionally) loaded into any template
I create an app called global_settings, and make sure it's included in my settings.INSTALLED_APPS tuple.
Django compiles templated text into nodes with a render() method that tells how the data should be displayed--I created an object that renders data by returnning values in my global_settings.py based on the name passed in.
It looks like this:
Now, in global_settings.py I register a couple tags: site_url for my example and min_test_time for your example. This way, when {% min_time_test %} is invoked from a template, it'll call get_min_time_test which resolves to load in the value=5. In my example, {% site_url %} will do a name-based lookup so that I can keep all 4 URLs defined at once and choose which environment I'm using. This is more flexible for me than just using Django's built in settings.Debug=True/False flag.
Note that for this to work, django is expecting global_settings.py to be located in a python packaged called templatetags under your Django app. My Django app here is called global_settings, so my directory structure looks like:
/project-name/global_settings/templatetags/global_settings.py
etc.
Finally the template chooses whether to load in global settings or not, which is beneficial for performance. Add this line to your template to expose all the tags registered in global_settings.py:
Now, other projects that need MIN_TIME_TEST or these environments exposed can simply install this app =)
在上下文处理器中,您可以使用以下内容:
In the context processor you can use something like:
John Mee 最后一部分的变体,对 Jordan Reiter 讨论的同一想法进行了一些阐述。
假设您的设置中有类似于 Jordan 建议的内容 - 换句话说,类似于:
进一步假设您已经有一个字典,其中包含您想要传递模板的一些变量,可能作为参数传递给您的视图。我们将其命名为
my_dict
。假设您希望 my_dict 中的值覆盖settings.GLOBAL_SETTINGS
字典中的值。您可以在您的视图中执行以下操作:
这使您可以全局确定可用于模板的设置,并且不需要您手动键入每个设置。
如果您没有任何额外的变量来传递模板,也不需要重写,您可以这样做
: Jordan 所拥有的是,对于他来说,
settings.GLOBAL_SETTINGS
会覆盖它与您的上下文字典可能共有的任何内容,而对于我的,我的上下文字典会覆盖settings.GLOBAL_SETTINGS
。 YMMV。Variant on John Mee's last part, with a little elaboration on the same idea Jordan Reiter discusses.
Suppose you have something in your settings akin to what Jordan suggested -- in other words, something like:
Suppose further you already have a dictionary with some of the variables you'd like to pass your template, perhaps passed as arguments to your view. Let's call it
my_dict
. Suppose you want the values in my_dict to override those in thesettings.GLOBAL_SETTINGS
dictionary.You might do something in your view like:
This lets you have the settings determined globally, available to your templates, and doesn't require you to manually type out each of them.
If you don't have any additional variables to pass the template, nor any need to override, you can just do:
The main difference between what I'm discussing here & what Jordan has, is that for his,
settings.GLOBAL_SETTINGS
overrides anything it may have in common w/ your context dictionary, and with mine, my context dictionary overridessettings.GLOBAL_SETTINGS
. YMMV.