Заметили, наверное, что в моем блоге начали чаще появляться куски кода? Это связано с тем, что выглядят они теперь лучше, а все благодаря плагину Pygments for WL Writer, который можно взять тут:
22 окт. 2009 г.
Django blog – обзор pluggable приложений для создания блога на django
Не помню кто, но кто-то точно :), утверждал, что джанго - платформа для создания собственного блога. Пишу на джанго уже 2 года, а про блоги на ней (на нем?) задумался только сейчас. Мой блог на blogger’е и это дает определенные преимущества в скорости индексации и pr блога.
Естественно, у платформы “специально для блогов” должно быть куча готовых решений. В принципе так и есть, но на все у меня, как всегда, не хватит ни сил, ни терпения, поэтому в обзор войдет только те, которые обновлялись не поздней чем месяц назад.
Итак, 3 pluggable приложения на django для создания блога:
- django-diario,
- blogmaker – UPD: не подходит, т.к. не обновлялся давно,
- django-basic-apps.blog (кусок pinax’а).
UPD: честно признаюсь, я забыл про byteflow напрочь, когда садился это писать. Только по этому byteflow и нет в данном посте, но думаю, про него итак достаточно написано.
Смотрю на каждое из приложений впервые, потому претендовать на абсолютную достоверность обзора не планирую. Как всегда, обзор будет более эмоционален и субъективен, чем нужно :). Комментарии приветствуются. Дельных комментаторов буду поощрять ссылкой с 10 своих сайтов на их ресурс (кому не нужны 10 обратных ссылок?).
django-diario
Не смотря на растущую популярность github’а хоститься на code.google.com - http://code.google.com/p/django-diario/. Актуальная версия (на момент написания) - 0.2, выпущенная 13th December 2008, но кому нужен релиз? Берем транк, который обновлялся 20 октября 2009 (опять же на момент написания - далее нмн). И сразу первая радость – в репозитории рядом с приложением лежит каталог examples, а в нем basic_blog.
Идем в каталог с basic_blog примером, запускаем
manage.py syncdb
Запускаем тестовый сервер, радуемся.
Скрин 1 – главная страница basic_blog’а
Скрин 2 – Админка basic_blog’а
Идем в пункт админки Entries и добавляем новый пост – ссылка Add entry.
Скрин 3 – Пункт админки “Создание нового поста” в basic_blog’а
Не густо. Одна надежда на пунктик “Advanced options”, который по умолчанию свернут. Жмем.
Скрин 4 – Подпункт “Advanced options” в пункте админки “Создание нового поста” в basic_blog’а, в доме который построил Джек.
Оказывается, тут скрывалась опция разметки для поста. Кстати наличие тут textile, например, не связано с наличием Python textile library у вас на компе. Теперь, кстати есть смысл ещё раз посмотреть на пункт админки “Entries”.
Скрин 5 – Пункт админки Entries в basic_blog’а
Комментарии излишни.
Главная страница блога теперь выглядит так:
Скрин 6 – снова главная страница в basic_blog’а, но теперь на ней есть пост.
Главная страница пока мало отличается от Weblog (ссылка вверху страницы) и страницы самого поста.
Так как я в принципе не владею ни одной из данных разметок (кроме HTML, который и есть Raw text в соответствии с подсказкой к полю Markup language), текст у меня получился без абзацев.
Придется лезть в документацию и исходники, т.к. увиденное не впечатляет. Из документации выясняется, что diary распространяется под LGPLv3 и сопровождена весьма не плохо документацией. Например, в файле install.txt описан процесс подключения RSS-фидов.
В urls.py нужно добавить:
from diario.feeds.entries import RssEntriesFeed, AtomEntriesFeed
entries_feeds = {
'rss': RssEntriesFeed,
'atom': AtomEntriesFeed,
}
urlpatterns = patterns(
...
(r'^blog/(?P<url>(rss|atom))/$', 'django.contrib.syndication.views.feed', {'feed_dict': entries_feeds}),
)
Попробуем. Идем в urls.py и обнаруживаем, что оно уже подключено!
Скрин 7 – RSS-фид basic_blog’а.
Ну тогда попробуем подключить фичу с тэгами в блоге (тоже описана в install.txt). Идем в urls.py и добавляем
(r'^weblog/tag/', include('diario.urls.tagged'))
а заодно и подсмотренная чуть позже
(r'^weblog/tag/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': entries_by_tag_feeds}),
- дял рсс фидов по тэгам. Строки
entries_by_tag_feeds = {
'rss': RssEntriesByTagFeed,
'atom': AtomEntriesByTagFeed,
}
уже почему-то добавлены. Ах да, в basic_blog’е в настройках не подключено приложение 'tagging' (пункт INSTALLED_APPS), а потому придется после его подключения пересоздать базу. Почле чего, ниже поля Body в редактировании поста (в админке) появиться поле Tags.
После произведенных манипуляций должна заработать возможность отбора записей по тэгам и генерация рсс фидов по тэгаи, правда перед этим вам ещё нужно создать шаблон entry_list_tagged.html – лично я на этом спекся (итак ясно, что получится, так зачем время тратить).
Процесс подключения комментарием очень похож на процесс подключения тэгов.
- Добавляем ‘django.contrib.comments’ в INSTALLED_APPS
- Добавляем в url.py
from diario.feeds.comments import RssCommentsFeed as RssWeblogCommentsFeed
from diario.feeds.comments import AtomCommentsFeed as AtomWeblogCommentsFeed
blog_comments_feeds = {
'rss': RssWeblogCommentsFeed,
'atom': AtomWeblogCommentsFeed,
}
urlpatterns = patterns(
...
(r'^blog/comments/(?P<url>(rss|atom))/$', 'django.contrib.syndication.views.feed', {'feed_dict': blog_comments_feeds}),
)
И наслаждаемся, если конечно не придется создавать шаблоны и пересоздавать базу :).
Так как diario использует django.contrib.sitemaps приводить тут процесс добавления карты сайта не уместно, пост все-таки не про контриб sitemaps.
Заключение
django-diario – прекрасная основа дял создания собственного блога. Берешь, изменяешь, добавляешь свое и радуешься жизни – минимум геморроя, максимум фана. При том, для моей задачи, к сожалению не подходит – мне нужно много пользователей во множестве блогов. Можно конечно, добавить профиль пользователю, а в админке фильтровать queryset по признаку “владелец блога”, но спрева хочется взглянуть на прочих кандидатов в блог-приложение-моего-сердца.
blogmaker
Тоже игнорирует моду и хостится на code.google.com - http://code.google.com/p/blogmaker/. На главной wiki-странице проекта пугающая надпись про совместимость с Django 0.96. Актуальная версия 0.6 (нмн). И первый неприятный сюрприз (не был бы сюрпризом, если б я был повнимательней) – последнее сообщение об ошибке датирется 6 августа 2009 (нмн), а транк менялся последний раз 10 января 2008. Если не ошибаюсь, то djnago 1.0 вышла в марте 2008, значит blogmaker об этом ничего не знает – жаль.
Заключение
Минус одын.
django-basic-apps.blog
Актуальная версия basic-apps- 0.6, но всем наплевать, так как хостится проект на модном github’е, а значит можно легко и просто забрать архив последней ревизией. Что мы и делаем.
Далее нужно установить basic-apps (setup.py install), создать новый проект, например “basicappsblog” и внести в код следующие изменения (опять же, не настаиваю на полном соответствии):
# settings.py
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'database.db'
...
# Можно временно, для тестирования, подключить шаблоны прям из пакета
TEMPLATE_DIRS = (
'C:/projects/not mine/django-basic-apps/basic/blog/templates'
...
INSTALLED_APPS = (
...
'django.contrib.admin',
'django.contrib.comments',
'basic.blog',
'basic.inlines',
'tagging',
'django.contrib.markup'
)
# urls.py:
...
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^blog/', include('basic.blog.urls')),
(r'^admin/', include(admin.site.urls)),
)
Далее делаем syncdb и можно смотреть что получилось:
Скрин 8 – Админка django-basic-apps.blog
Скрин 9 – Добавление поста django-basic-apps.blog
Теперь главная страница блога выглядит так:
Скрин 10 – главная страница блога django-basic-apps.blog
Страница поста открываться отказывалась, пока я не прописал в шаблоне django-basic-apps\basic\blog\templates\blog
{% load markup %}
Однако, после добавления оной заработали комменты:
Скрин 11 – страница комментирования поста в блоге django-basic-apps.blog
Заключение
Честно говоря, на данном этапе продолжать изучать django-basic-apps.blog уже не хочется, слишком уж сильно он завязан на остальных basic-apps, а удовольствие от его использования получить можно только в том случае, если использовать его как компонент pinax’а. Писать про pinax хочется ещё меньше, так как это отдельная большая задача.
Полезные ссылки:
- Серия статей о создании блога Ross’а Poulton’а: часть 1, часть 2, часть 3.
- Patrick Altman I Want To Move My Blog To Django – перечисление сторонних pluggble приложений для создания блога на django.
20 окт. 2009 г.
Хронометрия
Глеб Архангельский советует заниматься этим почаще.
Вечером 11 октября 2009 года я поставил себе программу ManicTime, которая помогает собрать сведения о том, чем же я бываю занят сидя за компом (фактически все время пока бодрствую).
Так вот, выяснилось, что комп был включен почти 66 часов, причем меня за ним не присутствовало (?!) почти 12 часов (после 10 минут отсутствия активных действий со стороны пользователя комп. считается не используемым).
Программировал я, сидя в Komodo Edit, с тех пор 11 с небольшим часов, а вот в браузере я провел 33 часа (!!!). Почти 5 часов в pidgin’е и полтора часа в консоли.
На написание бездарных постов в блог я потратил 20 минут :).
Вот так-то, можно теперь смело удалять эту прогу – про себя я почти все знаю.
19 окт. 2009 г.
Центр иностранных языков “Весь мир” на django-cms 2
Вчера был опубликован мой djangp-cms 2 сайт на сайте http://www.django-cms.org/ - http://www.django-cms.org/en/sites/the-whole-world/detail/. Примечательно и удивительно что руководство сайта самостоятельно перевели название сайта (я отсылал русскоязычный вариант).
Это второй сайт, который я отсылаю в публичные джанго-сайто-агрегаторы (о как!). Первый - http://www.djangosites.org/s/animals-ecougra-ru/.
18 окт. 2009 г.
Подмена понятий в новостях нефтегаза
Для начала ссылка: http://old.tsogu.ru/Newsitems/University/Headline.2009-10-16.2109.
“На встрече с первокурсниками в этом году не поднимались проблемы благоустройства, а значит с этим все в порядке.”
Фразу успешно можно заменить на:
“На встрече врачей-педиаторов не поднималась проблема старческого склероза, а значит проблему старческого склероза удалось полностью решить.”
У геологов и экологов традиционно куча проблем с устройством на работу. У меня есть несколько знакомых геологов (прикиньте, я ведь работаю в институте геоинформационных систем), далеко не все они работают по специальности.
Если первокурсники не задают вопросы о трудоустройстве это может значить только одно – для них этот вопрос решен. Как? Видимо, у многие готовые контракты на обучение с последующим трудоустройством, или они отчаялись работать по специальности ещё до поступления. Любой другой студент, с не решенной проблемой трудоустройства этот вопрос бы задал. Или найдутся несогласные?
13 окт. 2009 г.
Django schedule
Всем, кто по какой-то непостижимой причине до сих пор не в курсе, срочно смотреть http://github.com/thauber/django-schedule и демку тут: http://www.geburt-und-leben.com/calendar/.
Аппликуха просто классная. Нужна, естественно, для создания всяких-там календарей и пр. Умеет очень многое. Сейчас, например, я разбираюсь с интервалами повторения.
8 окт. 2009 г.
Django CMS 2.0 – божественно
Поставил и использую django cms 2.0. Кайф. прям из коробки она умеет большую часть того, что нужно простой и удобной CMS.
Приятней всего для меня была возможность использования placeholder’ов. Суть в настройках прописываете “места размещения” кусков контента на страницах, прописываете их же в шаблоне (которые тоже можно выбирать для каждой страницы) и наслаждаетесь возможностью подставлять в страницу разные плагины (текст, видео, ссылка и пр.). Естественно, плагинов может быть несколько в одном плейсхолдере.
Про многосайтовость и разделение прав на уровне пользователей/групп/ролей я вообще молчу. Экземпляр django-cms 2 скоро буду использовать для всех своих поделок в Concepter’е
В общем, очень хочется написать об этой ЦМС по больше, но не знаю чего именно. Давайте так, пишите в комменты вопросы по ЦМСке, а я буду на них отвечать и апдейтить статью. Каждый 10 комментарий получит денежное вознаграждение по webmoney.
UPD1. Django-CMS 2.0, на сколько мне известно, форк с django-cms. Удивительный факт: форк этот - не единственный, и далеко не последний. feincms– новая CMS, использующая все теже требования, что и предыдущие 2. Лично я, не осилил понять как и зачем работать Feincms… Про сравнение разных django CMS я уже писал…
UPD2. Конфиг-файл:
# -*- coding: utf8 -*-
import os
PROJECT_DIR= os.path.abspath(os.path.dirname(__file__))
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = (
('Ivan Markeyev', 'markeyev@concepter.ru'),
)
MANAGERS = ADMINS
TEST_DATABASE_CHARSET = "utf8"
TEST_DATABASE_COLLATION = "utf8_general_ci"
DATABASE_SUPPORTS_TRANSACTIONS = True
TIME_ZONE = 'Asia/Yekaterinburg'
SITE_ID = 1
USE_I18N = True
MEDIA_ROOT = os.path.join(PROJECT_DIR, 'media')
#ADMIN_MEDIA_ROOT = os.path.join(PROJECT_DIR, '../admin_media/')
MEDIA_URL = '/media/'
ADMIN_MEDIA_PREFIX = '/adminmedia/'
FIXTURE_DIRS = [os.path.join(PROJECT_DIR, 'fixtures')]
SECRET_KEY = '+++'
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.load_template_source',
'django.template.loaders.app_directories.load_template_source',
# 'django.template.loaders.eggs.load_template_source',
)
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.i18n",
"django.core.context_processors.debug",
"django.core.context_processors.request",
"django.core.context_processors.media",
"cms.context_processors.media",
)
INTERNAL_IPS = ('127.0.0.1',)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.doc.XViewMiddleware',
#'django.contrib.csrf.middleware.CsrfMiddleware',
'cms.middleware.user.CurrentUserMiddleware',
'cms.middleware.page.CurrentPageMiddleware',
'cms.middleware.multilingual.MultilingualURLMiddleware',
#'debug_toolbar.middleware.DebugToolbarMiddleware',
)
ROOT_URLCONF = 'urls'
TEMPLATE_DIRS = (
os.path.join(PROJECT_DIR, 'templates'),
)
LOCALE_PATHS = (
os.path.join(PROJECT_DIR, 'i18n', 'locale'),
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.admin',
'django.contrib.sites',
'tagging',
'django.contrib.sitemaps',
'cms',
'publisher',
'cms.plugins.text',
'cms.plugins.picture',
'cms.plugins.file',
'cms.plugins.flash',
'cms.plugins.link',
'cms.plugins.snippet',
'cms.plugins.googlemap',
'cms.plugins.teaser',
'cms.plugins.video',
'cms.plugins.twitter',
'mptt',
'reversion',
#'example.categories',
#'debug_toolbar',
'south',
# sample application
'sampleapp',
#'store',
'rosetta',
)
LANGUAGE_CODE = "ru"
gettext = lambda s: s
LANGUAGES = (
('ru', gettext('Russian')),
# ('fr', gettext('French')),
# ('de', gettext('German')),
('en', gettext('English')),
# ('pt-br', gettext("Brazil")),
)
CMS_LANGUAGE_CONF = {
'ru':['en'],
'en':['ru'],
}
CMS_TEMPLATES = (
('index.html', gettext('default')),
('nice.html', gettext('nice one')),
('cool.html', gettext('cool one')),
('long-folder-long/long-template-name.html', gettext('long')),
)
CMS_SOFTROOT = True
CMS_MODERATOR = True
CMS_PERMISSION = True
CMS_REDIRECTS = True
CMS_SEO_FIELDS = True
CMS_MENU_TITLE_OVERWRITE = True
CMS_HIDE_UNTRANSLATED = True
try:
from local_settings import *
except ImportError:
pass