Перевод интерфейса Typo на русский 3
Я практически закончил сабж. Осталось немного согласовать с trunk-ом. Если кому-то интересно попробывать beta-версию, напишите мне на dobrych [at] gmail.com. Интересно Ваше мнение прежде чем буду выкладывать в общее пользование.
XML-сервисы на Python. Часть первая. Создание и парсинг XML. 2
Недавно второй раз на практике столкнулся с серьезной задачей по работе с XML на Python. И второй раз был расстроен. К сожалению не все просто в Python настолько, насколько хотелось бы.
Говоря в общем, встроенная в последний Python (2.5) ElementTree не совсем хороший выбор, как по мне, для полноценной работы с XML. С помощью ElementTree удобно создавать XML-документы, но никак не парсить. Я был удивлен, что такая простая задача как принять XML-документ из переменной—окажется такой замороченной… ElementTree заточен для парсинга файлов (т.е. ему нужно передавать при открытии или путь или уже открытый файл). В моем случае я уже имел переменную из HTTP-запроса, обработанного Django. Несколько часов я плясал с бубном, сначала чтобы заставить принять XML-документ из переменной, потом уже с самим парсингом и получением аттрибутов тегов. В общем убил много времени впустую, что очень неприятно. В довесок ко всему общеизвестный факт что ElementTree имеет очень ограниченную документацию, поэтому время было потрачено дополнительно на гугление и ковыряние в его сырцах.
Хочу отметить что создание XML-документа с помощью ElementTree оказалось достаточно простым и удобным. А начинали мы именно с создания, поэтому и парсинг позже пытались делать тем же ElementTree.
В итоге, после всей возни, я решил для парсинга использовать отдельную библиотеку—Beautilful Soup. И работа сразу пошла очень быстро. Главное достоинство Beautilful Soup—это практически полная сериализация XML-документа в объекты Python. Что очень хорошо отражается на читаемости кода и очень удобно при отладке. Насчет создания документов с помощью Beautilful Soup, ничего сказать не могу, т.к. небыло времени для себя потестировать.
Из прошлого своего опыта также добавлю, что есть еще одна библиотека для работы с XML на Python—lxml. Она базируется на Cи библиотеках libxml и libxslt. Которые в свою очередь используются в большом количестве unix-приложений и других скриптовых языках. Прошлая моя задача была свзязана с выборкой данных из XML-документов с помощью Xpath. Так вот lxml и в частности libxml имеет хорошую и удобную реализацию Xpath. Так что рекомендую.
PS: Все написанное выше—сугубо личное мнение, на которое в принципе имею право :)
Ниже примеры кода.
# пример парсинга XML через Soup
from BeautifulSoup import BeautifulStoneSoup as Soup
def some_view(request):
message = Soup(request.raw_post_data)
some_obj = Obj(content = message.body.string, phone = message.sin.string)
# message.body - body это xml тег
# пример создания XML-документа
import elementtree.ElementTree as ET
# создаем документ
root = ET.Element("message") # рутовый элемент <message>
root.set("rid", "7idfndsi9s") # устанавливаем ему аттрибут
sn = ET.SubElement(root, "sn")
sn.text = "1039303"
body = ET.SubElement(root, "body")
body.set("content-type","text/plain")
body.text = "somte text content"
message = ET.tostring(root)
<message rid="7idfndsi9s">
<sn>1039303</sn>
<body content-type="text/plain">somte text content</body>
</message>
Проверка HTTP-запроса на аяксовость (ajax) 2
При написании приложения по принципам MVC с использованием Ajax, часто для одного и того же запроса нужно получить данные в двух отличных друг от друга вариантах—в чистом HTML и в XML/json для Ajax запроса. А т.к. один и тот же контроллер в MVC обрабатывает оба типа запроса и скорее всего было бы удобно для его обработки использовать один и тот же URL, надо как-то отличать их, чтоб знать в каком формате отдать данные. Если это POST-запрос то можно просто создать дополнительное поле/переменную в запросе, а если GET, то нужно или отдельный URL для каждого типа данных или дополнительный заголовок в запросе (см. ниже почему).
Проблема мне кажется больше именно в GET запросе. Если следовать правилам ReST, то контент полученный по URL должен быть кеширован, а в нашем случае будет кеширован первый формат, в котором контроллер отдаст контент. Было бы удобно чтоб контроллер делал проверку на наличие каких-то заголовков и отдавал в зависимости от них ответ в нужном виде, но вот кеширование этому помешает. Т.к. кеш скеширует контент на первый попавшийся запрос (Ajax/HTML) и для следующего отличного запроса может быть отдан контент в неверном формате. Конечно можно с помощью заголовков вообще отключить кеширование, но это неоправдано, т.к. в протоколе HTTP не зря предусмтрена такая функциональность.
В общем решением была бы возможность реагирования кеша на определенные заголовки от сервера. И да, это указано в стандарте HTTP и реализовано как клиентами так и серверами. Есть такой заголовок в стандарте HTTP—Vary:, обычно его называют Vary Header. Он необходим как раз для осуществления правильного кеширование в зависимости от его значения. По большому счету он нужен чтоб указать кешу для какого заголовка запроса скеширован данный URL. Т.е. контент в кеше теперь будет идентифицироваться не только по URL, но по URL + заголовок указанный директивой Vary. Например, если пользователь залогинен на сайт с использованием Cookie, тогда заголовок Vary должен выглядеть так Vary: Cookie. URL в это случае, например, будет /profile/ (профиль пользователя) и два разных пользователя, попав на страницу из одного кеша будут проверены с помощью директивы Vary на предмет Cookie и получат разный контент. Или например кеширование должно производиться с учетом языка пользователя, тогда директива будет выглядить так Vary: Content-Language.
Зачем это нужно в нашем случае? Все просто—практически все Javascript Toolkits используют заголовок HTTP_X_REQUESTED_WITH со значением ‘XMLHttpRequest’. Так что если мы поставим Vary: HTTP_X_REQUESTED_WITH, то оба запроса к одному URL но от разных инициаторов (сам браузер или javascript/ajax код) будут скешированы отдельно.
Вот такой интересный нюанс. Может кому-то пригодится в деле.
Подкасты про webdev 1
Последнее время стал увлекаться подкастами. К сожалению русскоязычных качественных очень мало. А на тему веб-разработок вообще нет (поправьте если ошибаюсь).
Хочу привести свою подборку англоязычных подкастов, которые слушаю.
- Начну с наиболее интересного для меня—Hivelogic Radio. В этом подкасте автор концентрируется на веб-разработке, как на дизайне так и на программировании. Очень интересные интервью с интересными людьми. В разработке есть акцент на Ruby on Rails. Со стороны аудио, подкаст сделан очень качественно. Приятно слушать.
- Следующий подкаст я слушаю не так давно, но у него довольно большой авторитет—FOO Casts: Podcasts from O’Reilly & Friends В нем освящается много технических вопросов, необязательно связанных с вебом, но все равно полезных для любого гика и разработчика. Качества звука тоже на высоте.
- Inside Silicon Valley—Подкаст, состоящий в основном из интервью с монстрами и просто успешными людьми из Силиконовой Долины. Качество хорошее, слушать интересно.
- Python411 Podcast—для фанов Python. Качество звука не впечатляет, но темы и интервью довольно интересные. Так что подкаст пожалуй действительно для фанатов Python. Освящаются вопросы не только веб-разработки, но и других специализаций в программировании.
- WebDevRadio—Действительно настоящий подкаст именно для веб-разработчика. Обсуждение новых технологий в вебе, интервью, относительно часты обновления. Советую.
- The Mac Attack—Подкаст про Mac, MacOSX и все что с ним связано. Как известно многие современные веб-разработчики и дизайнеры выбирают платформу Apple в качестве рабочей станции. Так что думаю будет просто интересно, а некоторым и полезно.
Typo 4.1 — обновляемся
Обновление моего блога.
На днях обновил свой блог на движке typo, до весрии 4.1
Впечатления пока что только приятные. Сразу бросается в глаза подчищенная админка. Большой плюс еще, что блог движок работает на rails 1.2 и заметный прогресс в том, что есть встроенная возможность локализации.
Процесс переезда прошел прозрачно, почти без бубна и плясок :-) Итак пошагово, для тех, кто будет повторять:
- Бекапим базу в двух вариантах—SQL-дамп и сериализованный YAML вариант. Первое делается через mysqldump или phpmyadmin, а второй вариант командой rails-backup в директории с rails-проектом блога.
- Обновляем rails и typo. Т.к. у меня все работает через rubygem, я просто запустил
sudo gem update
. После чего получил последние стабильные gems. - Останавливаем текущий процесс typo. Переименовываем директорию проекта и создаем заново проект с typo—
typo install my_typo_dir
- Переносим конфиги из старой в новую директорию (обычно это database.yml и mongrel_cluster.yml). И обновляем базу
rake db:migrate
. - После чего запускаем проект (у меня он работает через mongrel cluster), логинимся в админку и первым делом нам предлагается поменять контент в базе на новый лад. Нужно просто согласиться и блог готов к работе.
Если появились трудности при апдейте—пишите, чем смогу помогу.
PS: В рассылке видел, что у одного человека возникли проблемы при переезде с базой. У него полечилось через rails-backup и rails-restore
django: как создать html сообщение
Вот по следам недавних дискуссий в django-users пишу заметку как создавать имейлы с аттачами и html-ом.
Есть патчи в тикете #1541 для интеграции в саму джангу или можно воспользоваться примерами кода отсюда и отсюда.
django.vim
Обновился vim-овский файл синтаксиса для django. смотреть на vim.org
Добавили:- новую систему комментариев {# greeting #}
- улучшили подсветку ошибок, например {{ variable %} будет подсвечено как ошибка
django: работа с несколькими версиями
В связи с появлением в trunk-ветке django такой прикольной библиотеки, как newforms, пришлось на нескольких проектах переползать на trunk. При этом все остальные должны стандартно работать на версии 0.95
В системе стоит как раз 0.95 (в site-packages). Проекты работают все на связке mod_python + apache. При настройке mod_python для django-проекта используется директива PythonPath. С её помощью к путям поиска python-модулей добавляется директория с проектом. Поэтому достаточно положить дистрибутив django в ту же директорию где лежит проект.
А вот для отладки приложения приходится немного пошаманить. Я так и не разобрался в чем причина, но когда запускаешь python shell (python manage.py shell) в любом случае в списке директорий с модулями site-packages оказываются первее чем то, что добавляешь в PythonPath переменную окружения. В итоге получается что используется версия django, котрая стоит в site-packages (т.е. 0.95).
Решается всё довольно просто, но дошел я до этого не сразу, т.к. боролся чтоб всё было кошерно :-) (через python manage.py shell). Сначала грешил на ipython, но без него была та же петрушка. Наковырявшись вдоволь я сделал потом всё по быстрому и просто.
Надо установить две системные переменные в shell-окружении:- PYTHONPATH=’path_to_Django_project‘
- DJANGO_SETTINGS_MODULE=my_project.settings
После этого в любой директории набераете python или ipython и делаете импорты из моделей и работаете с ними.
openid enabled
У меня сабж :-)
Нашел наконец-то время разобраться с openid, как и предполагал ничего особо сложного нет.
Все делал по этим статьям: OpenID for non-SuperUsers OpenID delegation under Django and lighttpd
Теперь бы еще запустить свой openid сервер :-)
Для моего Typo блога всё свелось к нескольким манипуляциям.
- регистрация на myopenid
- создание yadis.xrdf файла
- конфигурация apache
- добавлении строчки кода в хидер темплейта блога
<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)"
xmlns:openid="http://openid.net/xmlns/1.0">
<XRD>
<Service priorioty="1">
<Type>http://openid.net/signon/1.0</Type>
<URI>http://www.myopenid.com/server</URI>
<openid:Delegate>http://dobrych.myopenid.com/</openid:Delegate>
</Service>
</XRD>
</xrds:XRDS>
Вот строки для конфигурации апача:
# OpenID
AddType application/xrds+xml .xrdf
RewriteCond %{HTTP_ACCEPT} application/xrds\+xml
RewriteCond %{HTTP_ACCEPT} !application/xrds\+xml\s*;\s*q\s*=\s*0(\.0{1,3})?\s*(,|$)
RewriteRule ^$ http://livedev.org/yadis.xrdf [R,L]
Header onsuccess set X-XRDS-Location http://livedev.org/yadis.xrdf
Вот строка, добавленная в шаблон
<meta http-equiv="X-XRDS-Location" content="http://livedev.org/yadis.xrdf">
Мультисайтовость в django trunk
Наконец-то появиалсь функциональность мультисайтинга в Django Framework. Напомню что раньше надо было для каждого сайта держать отдельную instance фреймвока (в смысле или отдельный fastcgi процесс или отдельно сконфигурированный виртуальный хост с mod_python).
В конфигурации проекта (settings.py) надо указывать SITE_ID, который в базе соответствует какому-то домену. И для каждого домена нужно было держать отдельный settings.py с соответствующим SITE_ID из базы.
Теперь в транк попал патч и новый middleware, который позволит в рамках одного проекта обслуживать несколько доменов. Домены будут определяться ”на лету”.
Теперь можно писать вот такие конструкции:
HOST_MIDDLEWARE_URLCONF_MAP = {
"company.com": "mydjango.app.company_urls",
"blog.example.com": "mydjango.app.blog_urls",
}
Подробнее на сайте автора и тикет.
Older posts: 1 2 3