Подтвердить что ты не робот

Django - Почему я вообще должен использовать render_to_response?

рассмотрим это:

return render(request, 'index.html', {..context..})
return render_to_response('index.html', {..context..})

С одной стороны, render чище и более питонично. С другой стороны, вы используете request как свой первый аргумент, который я считаю излишним и запутанным. Поэтому я начал задаваться вопросом о больших различиях...

Согласно документы:

render() совпадает с вызовом render_to_response() с context_instance, который заставляет использовать RequestContext.

Таким образом, разница заключается только в использовании RequestContext. Итак, что важно для RequestContext? Давайте посмотрим на docs снова:

специальный класс Context [...] действует несколько иначе, чем нормальный django.template.Context. Первое отличие состоит в том, что требуется HttpRequest в качестве первого аргумента.

Ok. Это почти не имеет значения

Второе отличие состоит в том, что он автоматически заполняет контекст с несколькими переменными, согласно вашим TEMPLATE_CONTEXT_PROCESSORS настройка [...] В дополнение к этим, RequestContext всегда использует django.core.context_processors.csrf [...] намеренно жестко закодирован и не может быть отключен TEMPLATE_CONTEXT_PROCESSORS установка.

Итак, это важная часть - убедитесь, что все обработчики контекста работают правильно, с акцентом на csrf. Так что, вернемся к первому примеру, это на самом деле то же самое:

return render(request, 'index.html', {...})
return render_to_response('index.html', {...}, context_instance=RequestContext(request))

Теперь, второй пример, очевидно, намного хуже, все это выглядит очень усложненным. Поэтому мой большой вопрос: Зачем использовать render_to_response вообще? Почему бы не обесценить его?

Другие вопросы, которые приходят на ум:

Я знаю, что это немного не по теме, но я надеюсь получить ответы, которые объяснят, почему render_to_response останавливается и\или примеры использования, где использование render_to_response будет предпочтительнее render (если они есть)

4b9b3361

Ответ 1

Большинство приложений используют render_to_response, поскольку это был рекомендованный по умолчанию вариант с самого начала до Django 1.3. Причиной сосуществования обоих является историческое, обесценивание render_to_response заставит много кода переписать, что не является вежливым в незначительных выпусках. Однако в этом потоке django-разработчиков, они говорят, что можно будет включить в шкалу устаревших версий 2.0.

Здесь цитата Рассел Кейт-Маги, один из разработчиков ядра Django. Keith-Magee отвечает на вопрос, который написал Джейкоб Каплан-Мосс, еще один участник Django, который поднимает вопрос об утомлении render_to_response:

Я думаю, мы должны отказаться от render_to_response() в пользу render(). render_to_response() - это просто render (request = None,...), правильно? Любые причина держать оба вокруг? Нет никакой особой причины держать оба вокруг, кроме отторжения кода, что влечет за собой отказ.

И Кит-Маги отвечает:

Это то, что у меня нет проблем с устареванием на 2.0 расписание, но перенося каждое использование render_to_response() по следующие 18 месяцев /2 выпуска, похоже, являются крайней мерой для вся пользовательская база при сохранении render_to_response() не предпринимать любые реальные усилия.

Никто не обсуждал эту усталость, но я думаю, что ответ на ваш вопрос таков: нет технической причины, это просто их намерение не принудительно обновлять всю кодовую базу в незначительной (по крайней мере, не большой) версии.

Ответ 2

Слишком долго; не читал

When context processors are applied

Когда вы используете RequestContext, сначала добавляются переменные, которые вы поставляете, а затем за любыми переменными, предоставляемыми процессорами контекста. Это означает, что процессор контекста может перезаписать переменную, предоставленную вами, поэтому будьте осторожны, чтобы избежать имен переменных, которые накладываются на те, которые поставляются вашими процессорами контекста.


Посмотрим сначала, как методы render_to_response и render определены.

def render_to_response(*args, **kwargs):
    """
    Returns a HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    httpresponse_kwargs = {'content_type': kwargs.pop('content_type', None)}

    return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)

def render(request, *args, **kwargs):
    """
    Returns a HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    Uses a RequestContext by default.
    """
    httpresponse_kwargs = {
        'content_type': kwargs.pop('content_type', None),
        'status': kwargs.pop('status', None),
    }

    if 'context_instance' in kwargs:
        context_instance = kwargs.pop('context_instance')
        if kwargs.get('current_app', None):
            raise ValueError('If you provide a context_instance you must '
                             'set its current_app before calling render()')
    else:
        current_app = kwargs.pop('current_app', None)
        context_instance = RequestContext(request, current_app=current_app)

    kwargs['context_instance'] = context_instance

    return HttpResponse(loader.render_to_string(*args, **kwargs),
                        **httpresponse_kwargs)

Нет ли лучшего способа принудительного применения RequestContext по умолчанию?

Примечание в разделе Subclassing Context: RequestContext

Если вы используете ярлык Djangos render_to_response(), чтобы заполнить шаблон содержимым словаря, ваш шаблон будет передан Context экземпляр по умолчанию (не RequestContext)

Из приведенного выше кода метод render_to_response вызывает метод loader.render_to_string, где параметр context_instance отмечен в этой строке.

Перечень кодов для метода render_to_string

def render_to_string(template_name, dictionary=None, context_instance=None,
                     dirs=None):
    """
    Loads the given template_name and renders it with the given dictionary as
    context. The template_name may be a string to load a single template using
    get_template, or it may be a tuple to use select_template to find one of
    the templates in the list. Returns a string.
    """
    dictionary = dictionary or {}
    if isinstance(template_name, (list, tuple)):
        t = select_template(template_name, dirs)
    else:
        t = get_template(template_name, dirs)
    if not context_instance:
        return t.render(Context(dictionary))
    # Add the dictionary to the context stack, ensuring it gets removed again
    # to keep the context_instance in the same state it started in.
    with context_instance.push(dictionary):
        return t.render(context_instance)

Разве мы не можем просто использовать декоратор с render?

Мы можем написать для этого декоратор, но ваш вопрос субъективен. Если это легко использовать или нет, трудно сказать. Это очень зависит от


Есть ли способ избежать передачи запроса в качестве аргумента?

render() совпадает с вызовом render_to_response() с аргументом context_instance , который заставляет использовать RequestContext.

class RequestContext определяется в этой строке. Список кодов для class RequestContext

class RequestContext(Context):
    """
    This subclass of template.Context automatically populates itself using
    the processors defined in TEMPLATE_CONTEXT_PROCESSORS.
    Additional processors can be specified as a list of callables
    using the "processors" keyword argument.
    """
    def __init__(self, request, dict_=None, processors=None, current_app=None,
            use_l10n=None, use_tz=None):
        Context.__init__(self, dict_, current_app=current_app,
                use_l10n=use_l10n, use_tz=use_tz)
        if processors is None:
            processors = ()
        else:
            processors = tuple(processors)
        updates = dict()
        for processor in get_standard_processors() + processors:
            updates.update(processor(request))
        self.update(updates)

Последний вопрос не нуждается в ответе, если вы понимаете, как работает код за Django.