Определение констант в Django

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

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

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

EDIT: Чтобы уточнить, я знаю о Template Context Processors и о том, как просто вставлять вещи в settings.py или какой-либо другой файл и просто импортировать.

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

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

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

Ответы

Ответ 1

Оба Luper и Vladimir являются правильными imho, но вам понадобятся оба, чтобы выполнить ваши требования.

  • Хотя константы не обязательно должны быть в settings.py, вы можете поместить их в любом месте и импортировать их из этого места в свой код view/model/module. Иногда я помещаю их в __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

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

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

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

Затем, построив обработчик контекста John Mee:

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

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

Ответ 4

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

Ответ 5

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

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

  • шаблоны не полагаются на представления, чтобы иметь в них глобальную информацию.
  • это DRY-er: приложение, определяющее глобальные параметры, может быть экспортировано во многие проекты, исключая общий код для проектов
  • шаблоны решают, имеют ли они доступ к глобальной информации, а не функции просмотра

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

У меня 4 среды - 2 dev и 2:

  • Dev: django-web server, url: localhost: 8000
  • Dev: веб-сервер apache: url: sandbox.com → разрешает 127.0.0.1
  • Prod sandbox server, url: sandbox.domain.com
  • Сервер Prod: url: domain.com

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

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

Django компилирует шаблонный текст в узлы с помощью метода render(), который указывает, как должны отображаться данные. Я создал объект, который отображает данные, возвращая значения в my 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, который разрешает загружать value = 5. В моем примере {% site_url%} будет выполнять поиск по имени, чтобы я мог сразу определить все 4 URL-адреса и выбрать, какую среду я использую. Это более гибко для меня, чем просто использование Django, встроенного в settings.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, поэтому моя структура каталогов выглядит так:

/project-name/global_settings/templatetags/global_settings.py и др.

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

{% load global_settings %}

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

Ответ 6

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

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

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

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

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.