Python: использование * args, ** kwargs в функциях-оболочках - PullRequest
7 голосов
/ 09 мая 2011

Я пишу функцию-обертку для render_to_response () Джанго, чтобы добавить обработку CSRF.

Логика такова:

def some_view (request)
    dictionary = {'context_param': some_param}
    dictionary.update(csrf(request))
    # ... view code here
    return render_to_response("a_template.html", dictionary)

render_to_response () имеет следующую подпись:

def render_to_response(*args, **kwargs)

Я хочу написать прозрачную оболочку - просто добавьте некоторые функции (упомянутые ранее) и оставьте другие вещи такими, какие они есть.Думаю, мне следует написать что-то вроде этого:

def csrf_response (request, *args, **kwargs):

    # Here I need to somehow extract dictionary from args or kwargs

    if dictionary is None:
        dictionary = {}
    dictionary.update(csrf(request))

    # And here I somehow need to pass dictionary into render_to_response() fot the furher processing
    return render_to_response(*args, **kwargs)

Итак, вопрос в том, каков наилучший способ извлечения необходимого параметра из args / kwargs (затем его изменения) и его дальнейшей передачи?

Кстати, код render_to_response () показался мне немного странным.Вот оно:

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 = {'mimetype': kwargs.pop('mimetype', None)}
    return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)

Что если кто-то вызовет его со всеми позиционными аргументами, так что kwargs будет пустым, но параметр mimetype будет указан как последний позиционный аргумент?Похоже, в этом случае его поведение будет неправильным.

1 Ответ

6 голосов
/ 09 мая 2011

Из-за того, как реализован render_to_response, единственный способ указать mimetype - использовать именованный аргумент. Все, что передается в качестве позиционного аргумента, передается в loader.render_to_string.

Методология извлечения определенных аргументов и передачи других действительно зависит от того, что вы делаете. Там нет ни одного "правильного" способа всегда делать это. Естественно, разные авторы имеют свои собственные предпочтительные соглашения.

Вместо вашего комментария # Here I need to somehow extract dictionary from args or kwargs вы можете использовать kwargs непосредственно в качестве словаря, а аргументы в качестве кортежа, потому что это именно то, что они есть. Для аргументов у вас нет выбора, кроме как утверждать (то есть предполагать) значение значения в каждой позиции.

Я лично предпочитаю, чтобы, если вы пишете код, который знает значения определенных аргументов, они должны быть объявлены в подписи, например:

def spam(session, name, *args, clear=True, **kwargs):
  # do something with session, name, clear
  return eggs(name, *args, **kwargs)  # if eggs requires name
...