7 основных ошибок, которые делают Django-разработчики

Коротко о том, какие бывают ошибки при разработке Django-приложений и как их избежать, чтобы не было мучительно больно

перевод статьи 7 Common Mistakes That Django Developers Make

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

Изобретенение велосипедов

Django имеет множество функций из коробки и гораздо больше возможностей дают сторонние пакеты. Попробуйте «погуглить» проблему, которую хотите решить, прежде чем что-то писать — возможно, уже существует многофункциональное решение.

Вы также можете использовать онлайн-каталог Django Projects, где категория «apps» (небольшие компоненты, используемые для создания проектов) насчитывает более 3200 проектов. Вот краткий образец интересных пакетов только с первых двух страниц листинга:

Бонусный совет: я настоятельно рекомендую начать новый проект Django с cookiecutter-django. Он поставляется с кастомной моделью пользователя, регистрацией через django-allauth, отправкой электронной почты через Anymail и многими другими настройками по умолчанию, связанными с безопасностью и развертыванием.

Монолитная структура приложения

Django — это слабо связанная платформа, которая не требует от вас создания веб-приложений каким-либо конкретным способом. У опытных разработчиков Django, однако, есть стандартный способ делать вещи.

Основной единицей веб-приложения Django является проект Django, который состоит из одного или нескольких приложений. Приложение Django — это автономный пакет, который должен делать только одно. Например, блог, приложение участия в чем-либо или календарь событий.

Приложения Django могут содержать модули Python, специфичные для Django модули (представления, URL-адреса, модели, формы и т. Д.), Статические файлы, миграции баз данных, команды управления, модульные тесты и многое другое. Вы должны разделить ваш проект на небольшие, многократно используемые приложения, используя простую логику.

\ecommerce_project      <= This is your Django project
    \cart               <= This is a Django cart app
    \checkout           <= This is a Django checkout app
    \products           <= This is a Django products app
    db.sqlite3          <= Your project database
    manage.py           <= Django project management utility

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

Написание толстых представлений и тонких моделей

Архитектура Django может быть описана как Model-Template-View (MTV) или Model-View-Template (MVT).

Model (модель) – это то, куда должна идти большая часть вашей бизнес-логики. Он определен в models.py и находится в каталоге приложения. Он также включает в себя запросы к базе данных, которые передают результаты в слои представления и шаблона.

View (представления) состоят из кода, который обрабатывает взаимодействие с пользователем, такое как отправка формы пользователем и формирование результатов из базы данных в соответствии с вашим шаблоном. Это определено в views.py.

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

Вы должны также использовать собственные менеджеры. Например, пользовательский менеджер может предоставить метод with_counts (), который возвращает список всех объектов OpinionPoll, каждый с дополнительным атрибутом num_responses, который является результатом агрегированного запроса. Для большего количества идей, проверьте встроенный UserManager.

Слишком много запросов на представление или неоптимизированные запросы

ORM Django часто обвиняют в том, что он делает слишком много запросов или они неоптимизированы. Но мы видим, что это происходит с ORM и в других средах.

Реальная проблема в том, что мы часто не знаем о проблемах производительности и их источниках. Как только вы выясните, какие у вас узкие места, вы сможете выбрать правильный подход для их устранения. Здесь вы можете многое сделать, но, скорее всего, это будет так:

  • Исправить простые ORM-запросы (привет предварительная выборка)
  • Настройка и оптимизация запросов ORM
  • Добавьте кеширование в нужных местах
  • Предоставить больше ресурсов

django-debug-toolbar — замечательный инструмент отладки. Вы можете использовать его для отслеживания проблем с производительностью в SQL-запросах, запросах, шаблонах, кэше и т. Д. Этот небольшой пакет поможет вам быстро выявить проблемы. Я настоятельно рекомендую использовать его.

Избыточные поля моделей

Поскольку запросы не могут использовать вычисляемые столбцы, а добавление реального столбца — всего лишь «создание миграций», разработчики часто дублируют поля, которые по-разному представляют одни и те же данные.

Довольно скоро половина ваших записей модели Vehicles будет иметь is_motorcycle == True и wheel_count == 4, и вы не будете уверены, какому полю доверять (подсказка: ни одному).

С Django вы можете рефакторировать несогласованные свойства, подобные этим, с помощью декоратора @property. Однако, хотя ORM позволяет вам обращаться к столбцам как к свойствам, обратное неверно, поэтому вам придется вручную рефакторировать каждый запрос.

Отсутствие индексов в моделях

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

Непоследовательная проверка данных

Модели Django могут быть связаны с одной или несколькими «формами», которые используются для создания и обновления экземпляров модели. Форма имеет много действий по-умолчанию, в частности, проверки, которая контролируется свойствами модели. Фактически, многие свойства модели существуют только для управления поведением форм по-умолчанию.

Многие разработчики Django забывают, что модель можно модифицировать не только посредством ее формы. Они также забывают отслеживать, какие ограничения находятся где. Не-ноль? Это на модели. Определите выбор для поля, явно перечисляя, какие значения оно может иметь? Это на форме. Уникальность? На модели. И так далее.

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

Резюме

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

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

Если вам понравилась эта статья, вы должны почитать плюсы и минусы Django в качестве веб-фреймворка для разработчиков Python.

Шесть лучших финансовых библиотек для Python

Python — востребованный язык в сфере финансов. Но сам по себе он не обладает тем количеством возможностей, которые привносят более 50 встроенных модулей. Например, если вам потребуется рассчитать кривую дисконтирования, то для этого необходимо будет привлечь экспоненциальную и логарифмическую функции, которые предоставляет встроенный математический модуль.

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

NumPy

NumPy является базовым модулем для выполнения финансовых расчетов с помощью Python. На 2018 год  NumPy входил в семерку наиболее популярных модулей, на данный же момент трудно найти финансиста, который бы с ним не работал. Библиотеки NumPy позволяют манипулировать матрицами и массивами, задействовать функции генератора случайных чисел, необходимые для определенных техник оптимизации вроде бустинга и бэггинга. Стоит отметить, что значительная часть основного кода здесь написана на C, что позволяет сгладить характерную для Python медлительность.

SciPy

SciPy собран из базовых функций NumPy, и крайне удобен в обработке финансовых данных, а также техниках обработки сигнала, линейной алгебре, статистике, интерполяции и оптимизации.

Matplotlib

Помимо обработки данных, не лишней будет возможность детально их изучить, и здесь на помощь приходит Matplotlibownload.htl, модуль визуализации, позволяющий создавать все виды таблиц и графиков в двух или трех измерениях. Не самый простой в освоении модуль, но если вы уже знакомы с Matlab, то проблем не возникнет — интерфейс Matplotlib во многом повторяет его. В любом случае, время, затраченное на освоение этого непростого модуля, всегда оправдывает себя, предоставляя пользователю самый широкий спектр возможностей по визуализации.

Pandas

Pandas, основанный на SciPy и NumPy, является достаточно распространенной библиотекой для работы с данными и их анализом. Pandas отлично показывает себя в управлении временными данными, и является незаменимым инструментов для отслеживания изменений цен с течением времени. Важно отметить, что изначально модуль pandas создавался разработчиками AQR, и лишь впоследствии перешел в открытый доступ.

В сумме NumPy, SciPy, matplotlib и pandas составляют популярный пакет, обычно именуемый просто как NumPy / SciPy. Несмотря на популярность самого пакета, его установка связана со значительными сложностями, и часто рекомендуется устанавливать его посредством Anaconda для последующего запуска в виртуальной среде. Проблема, однако, в том, что помимо NumPy / SciPy Anaconda устанавливает еще более 200 библиотек, что может поставить под вопрос эффективность этого метода.

Scikit-learn

Еще один модуль из состава Anaconda, в 2008 году признанный самым популярным модулем машинного обучения для Python. Классификация, кластеринг и другие популярные техники машинного обучения здесь подаются с визуализацией matplotlib, основной же код базируется на уже упоминавшихся NumPy и SciPy.

QuantLib 

Значительная часть квантов работает в оценке и структурировании, и для них в Python доступна QuantLib, одна из наиболее востребованных библиотек для C++ для операций оценки и расчета финансовых деривативов. Среди преимуществ QuantLib  однозначно выделяется характерная для кода в C++ быстрота, но отсутствие специализированной документации для Python делает освоение этого модуля достаточной непростой задачей. Однако и она оправдывает затраченные усилия, предоставляя быстрый и доступный инструмент для оценки в повседневной деятельности трейдера, где библиотека, написанная исключительно на Python, оказалась бы непростительно медленной.

Django formsets with attach

В Django есть отличная вещь – generic, которая содержит в себе такие конструкции как CreateView, UpdateView и т.д. Бывают ситуации, когда нам к форме модели необходимо добавить связанную сущность и записать это всё по одному сабмиту. В таком случае лучше всего прибгенуть к формсетам. Для начала необходимо описать сам формсет, который хотим использовать вместе с формой

from django.forms.models import inlineformset_factory
ImageFormSet = inlineformset_factory(Product, Image, extra=1, fields=['image'], can_delete=True)

и вот в самом UpdateView надо переопределить несколько методов:

class ProductUpdate(ProductMixin, UpdateView):
    def form_valid_formset(self, *args):
        for formset in args:
            if formset.is_valid():
                formset.save(commit=False)
                # Если нажали удалить у дочернего объекта
                for obj in formset.deleted_objects:
                    obj.delete()
                formset.save()
            else:
                return HttpResponseRedirect(self.get_success_url())

    def form_invalid_formset(self, *args):
        return self.render_to_response(self.get_context_data(**dict((a, a) for a in args)))

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        form_class = self.form_class
        form = self.get_form(form_class)
        return self.render_to_response(self.get_context_data(form=form, image_form=ImageFormSet(instance=self.object)))

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.get_form(self.form_class)
        image_form = ImageFormSet(self.request.POST, self.request.FILES, instance=self.object)
        if form.is_valid():
            return self.form_valid_formset(image_form)
        else:
            return self.form_invalid(form) 

Вот так быстро можно сделать вложения в момент создания и редактирования