Определение констант в Джанго - PullRequest
19 голосов
/ 28 октября 2010

Я хочу иметь некоторые константы в Django Projects.Например, скажем, константа с именем MIN_TIME_TEST.

Я хотел бы иметь возможность доступа к этой константе в двух местах: из моего кода Python и из любых шаблонов.

Каков наилучший способ сделать это?

РЕДАКТИРОВАТЬ: Чтобы прояснить, я знаю о процессорах контекстного шаблона и просто положить вещи в settings.py или некоторый другой файл и просто импортировать.

Мой вопрос: как мне объединить два подхода, не нарушая правило "Не повторяйся"?Основываясь на ответах до сих пор, вот мой подход:

Я хотел бы создать файл с именем global_constants.py, который будет иметь список констант (например, MIN_TIME_TEST = 5).Я могу import этот файл в любой модуль, чтобы получить константы.

Но теперь я хочу создать контекстный процессор, который возвращает все эти константы.Как я могу делать это автоматически, без необходимости перечислять их снова в словаре, как в ответе Джона Ми?

Ответы [ 7 ]

17 голосов
/ 28 октября 2010

И Люпер, и Владимир верны, imho, но вам нужно и то, и другое, чтобы выполнить ваши требования.

  • Хотя константы не нуждаются в , чтобы находиться в файле 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,
        }
    

Но это может быть излишним, если вы новичок в Джанго; возможно, вы просто спрашиваете, как поместить переменные в область видимости шаблона ...?

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)
6 голосов
/ 29 октября 2010

Чтобы построить ответы других людей, вот простой способ реализовать это:

В вашем файле настроек:

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

Затем, построив из John Mee'sконтекстный процессор :

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 голосов
/ 28 октября 2010

Попробуйте добавить его в settings.py вашего приложения. Конечно, чтобы использовать его в шаблоне, вам нужно сделать его доступным для шаблона, как и для любой другой обычной переменной.

2 голосов
/ 23 июля 2011

Процессоры контекста лучше подходят для обработки более динамических данных объекта - они определены как отображение в документации , и во многих постах они модифицируются или передаются представлениям.- не имеет смысла, что шаблон может потерять доступ к глобальной информации, потому что, например, вы забыли использовать специализированный контекстный процессор в представлении.Данные являются глобальными по определению и связывают представление с шаблоном.

Лучшим способом является определение пользовательского тега шаблона.Таким образом:

  • шаблоны не полагаются на представления для передачи в них глобальной информации
  • это СУХОЙ: приложение, определяющее глобальные настройки, может быть экспортировано во многие проекты,устранение общего кода в проектах
  • шаблоны решают, имеют ли они доступ к глобальной информации, а не к функциям представления

В приведенном ниже примере я имею дело с вашей проблемой - загрузка в этом MIN_TIME_TESTпеременная - и проблема, с которой я обычно сталкиваюсь, загружая URL-адреса, которые меняются при изменении среды.

У меня есть 4 среды - 2 разработки и 2 производства:

  • Dev: django-web сервер, url: localhost: 8000
  • Dev: веб-сервер apache: url: sandbox.com -> преобразуется в 127.0.0.1
  • сервер песочницы Prod, URL-адрес: sandbox.domain.com
  • Сервер Prod: url: domain.com

Я делаю это для всех своих проектов и сохраняю все URL в файле global_settings.py, чтобы он был доступен из кода.Я определяю пользовательский тег шаблона {% site_url%}, который можно (необязательно) загрузить в любой шаблон

. Я создаю приложение с именем global_settings и проверяю, включен ли он в мой кортик settings.INSTALLED_APPS.

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)

Теперь в 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 будет расположен в пакете Pythonпод названием templatetags под вашим приложением Django.Мое приложение Django здесь называется global_settings, поэтому моя структура каталогов выглядит следующим образом:

/ имя-проекта / global_settings / templatetags / global_settings.py и т. Д.

Наконец, шаблон выбирает, загружать ли в globalнастройки или нет, что выгодно для производительности.Добавьте эту строку в шаблон, чтобы отобразить все теги, зарегистрированные в global_settings.py:

{% load global_settings %}

Теперь другие проекты, для которых требуется MIN_TIME_TEST или которые доступны в этих средах, могут просто установить это приложение =)

2 голосов
/ 28 октября 2010

Используйте контекстные процессоры , чтобы ваши константы были доступны во всех шаблонах (settings.py - хорошее место для их определения, как сказал Владимир).

0 голосов
/ 29 октября 2010

Вариант последней части Джона Ми с небольшим уточнением той же идеи, которую обсуждает Джордан Рейтер.

Предположим, в ваших настройках есть что-то похожее на то, что предлагал Джордан - другими словами, что-то вроде:

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 , YMMV.

0 голосов
/ 28 октября 2010

В процессоре контекста вы можете использовать что-то вроде:

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