Блог по Ruby in Rails

блог по Ruby on Rails


четверг, 8 апреля 2010 г.

Пример использования Django 1.1 на Google App Engine

Я являюсь постоянным читателем сайта Hacker News. Примерно раз в месяц там создаются темы, где создатели стартапов и сочувствующие ищут себе сотрудников. Отдельный раздел для вакансий на этом сайте доступен только для фирм, которые участвуют в программе инвестирования Y Combinator. Кто-то предложил создать сторонний сайт вакансий специально для остальных пользователей этого сайта. Я решил реализовать эту идею, а заодно и получить практический опыт использования фреймворка Django более-менее свежей версии на платформе Google App Engine.

Так получился сайт Jobs for hackers с открытым исходным кодом. Созданный сайт использует авторизацию на основе учетных записей Google Account, так что если вы уже пользуетесь любым сервисом гугла, то дополнительно регистрироваться вам не нужно. Если же вы захотите на основе этого кода создать свой проект, где потребуется своя система регистрации и авторизации, то советую начать с чтения вот этого поста на английском языке, там есть ссылка на исходный код такого проекта тоже на Django 1.1 поверх Google App Engine.

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

Любой разработчик, который использует в своей работе встроенное в Google App Engine хранилище Datastore, наверняка сталкивался с проблемой постраничной выборки записей. Пока что нет масштабируемого встроенного решения, а статьи гугла, где встречается неработающий код, не всегда помогают. Но поиск по гуглогруппе App Engine позволил найти довольно изящный код, немного патченая версия которого находится тут. Пришлось закомментировать место в этом кода, где используется класс db.PolyModel, если в вашем коде этот класс нужен, то дайте знать, вместе что-нибудь придумаем. Вот пример постраничной навигации из файла views на основе того кода :

from jobs.models import Job
from pager import PagerQuery
PER_PAGE = 10
bookmark = request.GET.get('bookmark')
query = PagerQuery(Job).filter('status =', 'published').order('-published_at')
# это эквивалентно jobs = Job.all().filter(...).order(...)
prev, jobs, next = query.fetch(PER_PAGE, bookmark)

Еще поначалу во время разработки я думал разделить программную часть сайта на две половины. Там, где не нужны были сложные шаблоны, я думал не использовать Django, а ограничиться более простым фреймворком webapp. Но постоянные ошибки UnacceptableVersionError, которые то появлялись, то пропадали при странных обстоятельствах после многочисленных исправлений, заставили перевести весь код под управление Django. Всё из той же гуглогруппы я узнал, что фреймворк webapp, который использует шаблоны Django версии 0.96, при загрузке выполняет код import django, перед которым нельзя вклиниться и выполнить вызов use_library. Если кому-то из вас удалось это обойти, дайте знать, может когда-то понадобиться для оптимизации. Хотя чувствую, что вся эта затея является классической преждевременной оптимизацией, поскольку никаких числовых показателей для оценки производительности я не измерял.

Не до конца еще пока решил вопрос с кешированием статических файлов. Для предпоследней версии SDK 1.3.1 в списке изменений указывалась автоматическая выдача Http кода 304 Not Modified для статических файлов. Причем в багтрекере была приписка, что такое поведение будет только на серверах App Engine, для тестового сервера из SDK, который используется при разработке, файлы будут загружаться постоянно. По факту сервера App Engine работают не так, как ожидается. Вместо кеширования на год или еще какой-то большой срок, повторной загрузки файлов на клиента удается избежать только 10 минут. Недавно вышла следующая версия SDK 1.3.2, я еще не успел посмотреть как там с загрузкой статики. Если ничего не изменилось, то придется писать свой обработчик для файлов стилей, картинок и джаваскрипта.

Приветствуется также критика перевода этого поста на английский язык.

Комментариев нет:

Отправить комментарий