Перевод статьи: Bottle, full stack without Django
Автор: Тьяго Авелино (Thiago Avelino)
Эта заметка в блоге основана на лекции, которую я прочитал здесь, в Бразилии. Посмотрите слайды!
Bottle - это веб-микрофреймворк, совместимый с WSGI, который зависит только от стандартной библиотеки Python и совместим с Python версий 2.6, 2.7, 3.2, 3.3 и 3.4. Весь исходный текст фреймворка умещается в одном файле. Он был создан Марселем Хеллкэмпом (Marcel Hellkamp - @defnull) и поддерживается сообществом, образовавшимся вокруг этого фреймворка.
Django - это прагматичный фреймворк для быстрой веб-разработки, который написан на Python, использует стандарт MTV (model-template-view - модель-шаблон-представление). Изначально он был создан как система для управления сайтом журнала в городе Лоуренс, в Канзасе. Стал проектом с открытым исходным кодом, был опубликован под лицензией BSD в 2005 году. Название Django фреймворк получил в честь джазового музыканта Джанго Рейнхардта. Django стал очень известен благодаря поставке с "батарейкам", то есть благодаря нескольким библиотекам, добавленным к основному коду фреймворка для упрощения разработки. Вместе с фреймворком эти библиотеки сформировали так называемый "полный стек".
Прагматичный - значит ориентированный на решение практических, реальных задач с чётко определённой целью. Другими словами, команда разработчиков Django приняла некоторые архитектурные решения, а пользователи Django следуют этой архитектуре, не имея возможности легко её поменять.
Хорошо ли, если вместе с веб-фреймворком поставляются "батарейки"? Если вы согласны использовать всё, что даёт вам фреймворк, то ответ - да. Однако, не все веб-проекты одинаковы.
В большинстве проектов используется не более 80% возможностей Django. В тех случаях, когда используется не более 50% возможностей, мы вынуждены платить за все, что было предусмотрено архитектурой Django. То есть теряем в производительности, потому что в Django имеется множество модулей, которые не используются, но по-прежнему продолжают работать. Когда же мы используем микрофреймворк, мы берём на себя роль архитектора приложения. Поскольку у нас нет предопределённой архитектуры, нам нужно время, чтобы определить архитектуру приложения.
Все пакеты Python, которые имеются в библиотеке Django, в микрофреймворке могут быть заменены!
SQLAlchemy существовал до Django (да, до Django) и начиная с 2005 года появилась команда, которая стала заниматься разработкой ORM. Команда же разработчиков Django занимается одновременно и разработкой фреймворка и разработкой ORM. Я думаю, что не стоит говорить о том, что результат работы специалистов обычно бывает лучше, чем результат работы универсалов.
Структура модели:
class Entity(Base): __tablename__ = 'entity' id = Column(Integer, Sequence('id_seq'), primary_key=True) name = Column(String(50)) def __init__(self, name): self.name = name def __repr__(self): return "<Entity('%d', '%s')>" % (self.id, self.name)
Обходное решение для тех, кто не использует Django и кому нужно работать с формами - это WTForms, которые были созданы в 2008 году и поддержка которых продолжается до сих пор!
Структура формы:
class UserForm(Form): name = TextField(validators=[DataRequired(), Length(max=100)]) email = TextField(validators=[DataRequired(), Length(max=255)])
Jinja2 - это современный удобный для дизайнеров язык шаблонизации для Python, который был создан по образцу шаблонов Django. Он быстрый, широко используется и может быть дополнительно защищён изоляцией рабочего окружения.
Структура шаблона:
<title>{% block title %}{% endblock %}</title> <ul> {% for user in users %} <li><a href="{{ user.url }}">{{ user.username }}</a></li> {% endfor %} </ul>
Использование Alembic начинается с создания среды миграции. Это каталог сценариев, которые относятся к отдельному приложению. Среда миграции создаётся единожды, а затем поддерживается совместно с исходным кодом самого приложения.
Структура миграции:
revision = '1975ea83b712' down_revision = None from alembic import op import sqlalchemy as sa def upgrade(): pass def downgrade(): pass
Как создать обновление и откат:
def upgrade(): op.create_table( 'account', sa.Column('id', sa.Integer, primary_key=True), sa.Column('name', sa.String(50), nullable=False), sa.Column('description', sa.Unicode(200)), ) def downgrade(): op.drop_table('account')
Структура модификации таблицы:
""" $ alembic revision -m "Add a column" """ revision = 'ae1027a6acf' down_revision = '1975ea83b712' from alembic import op import sqlalchemy as sa def upgrade(): op.add_column('account', sa.Column('last_transaction_date', sa.DateTime)) def downgrade(): op.drop_column('account', 'last_transaction_date')
Здесь было продемонстрировано всё, что можно найти в стеке Django. Я писал эту заметку для не для того, чтобы принизить Django. Я лишь показал, что существуют другие полностековые решения для разработки приложений. Многие люди используют Django, не понимая экосистемы Python. В наше время Django предоставляет множество готовых решений, что заставляет некоторых разработчиков лениться и не наращивать мастерство в проектировании архитектуры приложения.
Помогайте Bottle. Мы - растущее сообщество. Чтобы внести свой вклад в код Bottle, обратитесь к списку открытых задач. В случае сомнений можно обратиться в список рассылки или в IRC-канал.
Считаю, что в статье тема не раскрыта. Не понятно, какая такая особенная архитектура приложения имелась в виду, которая никак не сочетается с Django. Перечислено несколько средств, которые в чём-то заменяют средства, имеющиеся в Django. Без сомнений, SQLAlchemy заткнёт за пояс джанговский ORM. Безусловно, Jinja2 - очень быстрый шаблонизатор, быстрее джанговского. Но стоит иметь в виду, что в Django все эти средства глубоко интегрированы друг с другом.
Например, в Django есть модельные формы, которые позволяют не создавать подробное описание формы, а автоматически получить это описание из описания модели. При необходимости модельную форму можно даже чуть-чуть подправить, указав какие поля не нужно отображать на форме, какие дополнительные поля, которых нет в модели, нужно добавить к форме, в каком порядке должны следовать поля, можно переопределить отдельные поля формы, определить особые методы валидации и т.д. В простейшем случае описание всей формы ограничивается парой строчек, но если нужно - можно получить гибкость, которую дают обычные формы.
Другой пример - в Django миграции можно сгенерировать автоматически. Автоматическая генерация даже умеет определять переименованные поля. А если же автоматика не сработала корректно, то автоматически сгенерированный код миграции можно подправить и руками.
Наконец, в комплекте с Django имеется административный интерфейс, для которого можно определять собственные классы для редактирования таблиц. В большинстве случаев этот административный интерфейс позволяет сэкономить время на создании шаблонов и написании представлений для просмотра и редактирования таблиц. Да, его возможности ограничены, но ведь в комплекте с Bottle ничего подобного нет, а если и есть в сторонних модулях, то наверняка такие модули тоже окажутся недостаточно интегрированными с ORM или модулем форм - придётся писать дополнительный код, который предоставит необходимую информацию этому модулю.
Я сам в своих проектах использую Django, но для некоторых задач он действительно избыточен. Например, в одной из прошлых своих заметок я писал Тайловый сервер на основе Python, Mapnik и Bottle. Денис Рыков, материалами которого я воспользовался, тоже писал тайловый сервер, воспользовавшись фреймворком Bottle. Для себя я решил, что если приложение не работает с собственной базой данных, а берёт информацию из сторонних источников и занимается лишь её преобразованием, или выполняет какие-то действия по требованию, то лучше использовать Bottle, т.к. в нём нет избыточных возможностей, а сам он обладает минимумом зависимостей и работает с любой версией Python.