0% нашли этот документ полезным (0 голосов)
446 просмотров29 страниц

Devconf Svarga

Загружено:

Alexander Solovyov
Авторское право
© Attribution Non-Commercial (BY-NC)
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd
0% нашли этот документ полезным (0 голосов)
446 просмотров29 страниц

Devconf Svarga

Загружено:

Alexander Solovyov
Авторское право
© Attribution Non-Commercial (BY-NC)
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd
Вы находитесь на странице: 1/ 29

Разумная альтернатива Django

Александр Соловьëв
Кто здесь?

• 4 года опыта работы с Django


• Автор и мейнтейнер Byteflow
• И всë такое
Django — это клëво

• Детерминированность окружения
• Модульность приложений
• Документация
Ложки дëгтя

• ORM
• Templates
• URLs
• Forms
• Команды
Django ORM

• Никаких проблем, пока всë просто


• Сырой SQL, когда всë сложно
• Не элегантно, но можно
SQLAlchemy

• Чуть более многословная


• Простые случаи — многословнее, чем в Django
• Управляется со сложными случаями
Django Templates

• Скорость — низкая
• Деградирует от вложенности (extends/include)
• Ограниченность синтаксиса
• Прячет Exception’ы
• Низкоуровневый парсер
Jinja2

• Похожа на шаблоны Django


• Скорость — высокая
• Возможности — пошире
– {{ dict[key] }}
– {{ data|filter(oh, my) }}
– даже в Django уже сделали почти нормальный if ;-)
• Templatetag’и — сложнее
• Макросы!
Макросы в Jinja2

{% macro render_post(post) %}
<time>{{ post.time }}</time> {{ post.title }}
{% endmacro %}

{% block content %}
<h1>{{ render_post(posts[0]) }}</h1>

{% for p in posts[1:] %}
<p>{{ render_post(p) }}</p>
{% endfor %}
{% endblock %}
urlresolvers vs Werkzeug

• Простой пример

url(r'(?P<name>\w{3,})', view)

Rule('<name(minlength=3)>', view)

• Конверторы: '<int:id>', '<float:value>'


• Код легко читать и расширять
Django forms

• Неприятная смесь логики и представления внутри


• Слегка странный API
(например clean_<fieldname> не принимает значение)
• Тяжело строить сложные формы
WTForms

• API очень похож на django.forms


• Но чище (как и код внутри WTForms)
• Сложные случаи легко решаются
– FormField
– FieldList
Команды

• Привет, Java! 1 команда — 1 модуль


• Каждая команда — класс
• Тяжеловесно
• Многословно
• Неудобно
Opster

@command(usage='[-l HOST] [-p PORT]')


def runserver(listen=('l', 'localhost', 'ip to listen on'),
port=('p', 5000, 'port to listen on'))
'''Run development server'''
print 'Success'

> ./yourscript help runserver


yourscript runserver [-l HOST] [-p PORT]
Run development server

options:
-l --listen ip to listen on (default: localhost)
-p --port port to listen on (default: 5000)
Выводы

• Отдельные проекты лучше


• Любой из них можно использовать с Django
• Но что останется от неë самой?
• И сторонние приложения не готовы к этому
Svarga

• Меньше 2 тысяч строк


• Django-like look&feel
• Глобальное окружение
• Батарейки
Глобальное окружение

from svarga import env


from svarga.shortcuts import as_html

@as_html('hello.html')
def hello():
return {'name': env.request.args['name']}
Глобальное окружение

• env.(settings | request | sqla | jinja | user | ...)


• Окружение доступно отовсюду
• request — это запрос (а не солянка, как в Django)
• Практично
Приложения

• Просто пакеты а-ля Django


• С опциональной инициализацией:

app/__init__.py:

def init(settings, env_class):


settings.add_template_path('blog', 'templates')

template:

{% extends "blog/base.html" %}
Модели

• Изначально — прослойка над SQLAlchemy


• Поддерживают разные бекенды
– GAE
– MongoDB
– любой другой
• Нет общего API запросов
• Генерация метаданных (например, для ModelForm)
Декларация моделей

class Card(Model):
number = models.IntegerColumn()

class Question(Model):
card = models.ForeignKeyColumn(Card, backref='questions')
number = models.IntegerColumn()

class Answer(Model):
question = models.ForeignKeyColumn(Question, backref='answers')
SQLAlchemy FTW

q = (Question.objects
.eager(Question.card, Question.answers)
.filter_by(number=number)
.join(Card).filter_by(number=card)
.one())
Батарейки

• Сессии
• Аутентификация
• Админка (в процессе)
• Bundle'ы
Bundle

from svarga.shortcuts import as_html, bundle

class TestBundle(bundle.Bundle):
@bundle.expose('/')
@as_html('test/entry.html')
def entry(self):
return {'param': 'eter'}
Bundle

from svarga.core.routing import Map


from views import TestBundle

urls = Map(
TestBundle('name1', '/prefix1'),
TestBundle('name2', '/prefix2'),
)
Админка

• Основана на bundle'ах
• Требует декларации
class SampleAdmin(ModelAdmin):
class Meta:
menu = ['Sample Admin', 'Test']
model = Sample
• Легко расширяется
Небезупречно

• Нас мало
• И документации тоже
(но библиотеки документированы)
• Тестов нет :(
• Готового кода немного
• Нет крупного коммерческого проекта за плечами
Утешение

• Нет застоя
• Использовать не страшно — кода немного
• Я рассказал не про все плюшки
(не забывайте об отладчике из Werkzeug ;-)
Welcome
• http://svarga.piranha.org.ua/
• irc://freenode.net/#svarga
[email protected]

Вам также может понравиться