13 нояб. 2013 г.

Разработчики Python VS Django

Во многих компаниях давно использующих python недолюбливают django. Раньше мне было не вполне понятно почему. Я считал это снобизмом. Теперь уверился, что джуниоры, начинающие свой практический путь с использования только фреймворков теряют потенцию искать решение самостоятельно. Первое, что они делают, когда сталкиваются с проблемой - гуглят готовое решение или желательно сразу батарейку. Если удалось найти решение сразу на стэковерфлоу - это победа. Скорей всего, люди писавшие ответ уже подумали, а значит нам думать и вовсе не нужно.Если ошибочное мнение повторено еще и в чьем-нибудь бложике, так вообще здорово. Ты на верном пути, будущий Лайнус Торвальдс. Проблемы начинаются потом. Решение нужно масштабировать/поддерживать/развивать, а понимания того, как оно работает нет.

Порой доходит до совсем смешного. Предположим некое API, в одном из методов принимает два POST параметра, для которых по сути не нужны ни валидаторы диапазона, ни проверка ввода. Как это правильно делать с точки зрения Django? Надо написать форму!

class DjangoForm(forms.Form):
    param1 = forms.CharField(required=False)
    param2 = forms.CharField(required=False)


def testFormView(request):
    form = DjangoForm(request.POST)
    if form.is_valid():
        param1 = form.cleaned_data['param1']
        param2 = form.cleaned_data['param2'] 

Но в рамках того же проекта на django можно просто обработать POST-параметры:
def testPOSTView(request):
    if request.method == 'POST':
        param1 = request.POST.get('param1')
        param2 = request.POST.get('param2') 

Возьмем для простоты улучшенный RequestFactory из https://djangosnippets.org/snippets/2231/ и напишем простяцкий тест:
request = RequestFactory().post('/submit/', {'param1': 'value1', 'param2': 'value2'})


def timeit(func, times):
    start = time.time()
    for i in range(0, times):
        func(request)
    return time.time() - start


def main():
    print timeit(testFormView, 10000)
    print timeit(testPOSTView, 10000)

Результат этого теста 1.77991509438 против 0.0828511714935.

9 комментариев:

Roman Gladkov комментирует...

Использовать param2 = request.POST.get('param2') и словить весь набор инъекций

tier комментирует...

Очень не хватает вывода в конце.
А также в середине - какого-то объяснения, зачем вообще заговорили о том, что POST-параметры доступны из request.POST напрямую, а не из django-формы после валидации.

TUMS комментирует...

Логично, учитывая что форма еще и валидацией занимается.

Тут дело не в том что Джанго тормозит, а в том что разработчик не понимает что Джангу и ее компоненты не нужно использовать прям везде, а можно обойтись более "низкоуровневыми" решениями с выигрышем ресурсов, и возможной лишь ценой удобства.

Так что опять же - проблема не в инструменте, а в руках.

Ivan Markeyev комментирует...

Спасибо за существенные замечания. Согласен со всеми комментаторами, вопрос в большей степени в понимании инструмента, а не в инструменте.

@Roman Gladkov и @TUMS, даже если использовать валидацию из фреймворка вне форм, будет быстрей. Проверьте ;).

@tier, пост был написан более года назад и контекстом этого поста было создание нагруженного API, в котором наиболее важна производительность - это вместо выводов, о которых вы говорите. Если нужна производительность - опускай решение на более низкий уровень.

Кирилл Кузьминых комментирует...

> Решение нужно масштабировать/поддерживать/развивать ...

Вот как раз в этом аспекте я бы предпочёл использовать решение на формах. Т.к. в рамках "развивать" через полгода может потребоваться добавить ещё парочку параметров в post-запрос, при этом с валидацией, десериализацией и осмысленным выводом сообщений об ошибках. И вот тут решение с прямым обращением к request.POST становится дико не красивым и сложно "поддерживаемым".

Если стоит вопрос производительности, то для начала можно будет попробовать заменить джанговские формы на другие имеющиеся реализации. И уже в последнюю очередь думать про прямую обработку параметров во view-шке.

Ivan Markeyev комментирует...

В рамках api, которое сломается если просто взять и добавить, не понадобится.

dustin комментирует...


@Roman Gladkov ничего страшного в этом коде не вижу ) Все зависит от дальнейшего кода. Никаких инъекций не будет если использовать стандартный ORM без raw queries, извращений с extra(), custom sql. В противном случае обрабатывайте дополнительно. В шаблонах от XSS защищает automatic html escaping пока насильно не вырубили.

skiby комментирует...

Уважаемые, так а что вы хотели?
Те, кто занимается разработкой на Django (с нуля) имеет цель - решить вопрос. Зачастую, мало имеет значения милисекунды и проч.
Поэтому и идет поиск батареек, готовых решений и т.д.
Не увеличить быстродействие, fps, оптимизировать использование памяти и запросы к базе, а построить сайт/webприложение.
Кто-то копает глубже в python, а кому-то хватает и явных циклов без лямбды.

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

Ivan Markeyev комментирует...

Наверное имелись в виду RPS, а не FPS?
Я указал свой контекст при написании статьи, в нем производительность важна.