Python: использование *args, **kwargs в функциях-оболочках
Я пишу функцию-обертку для 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 ответ
Из-за того, как render_to_response
реализован, единственный способ указать mimetype - использовать именованный аргумент. Все, что передается в качестве позиционного аргумента, будет передано loader.render_to_string
,
Методология получения определенных аргументов и передачи других действительно зависит от того, что вы делаете. Там нет ни одного "правильного" способа всегда делать это. Естественно, разные авторы имеют свои собственные предпочтительные соглашения.
На месте вашего комментария # Here I need to somehow extract dictionary from args or kwargs
Вы можете использовать kwargs непосредственно как словарь, а args как кортеж, потому что это именно то, что они есть. Для аргументов у вас нет выбора, кроме как утверждать (то есть предполагать) значение значения в каждой позиции.
Я лично предпочитаю, чтобы, если вы пишете код, который знает значения определенных аргументов, они должны быть объявлены в подписи, например, так:
def spam(session, name, *args, clear=True, **kwargs):
# do something with session, name, clear
return eggs(name, *args, **kwargs) # if eggs requires name