22 окт. 2009 г.

Pygments в Windows Live Writer для подсветки кода

Заметили, наверное, что в моем блоге начали чаще появляться куски кода? Это связано с тем, что выглядят они теперь лучше, а все благодаря плагину Pygments for WL Writer, который можно взять тут:

http://cid-0d9bc809858885a4.skydrive.live.com/browse.aspx/DevHawk%20Content/Pygments%20for%20WL%20Writer

Django blog – обзор pluggable приложений для создания блога на django

Не помню кто, но кто-то точно :), утверждал, что джанго - платформа для создания собственного блога. Пишу на джанго уже 2 года, а про блоги на ней (на нем?) задумался только сейчас. Мой блог на blogger’е и это дает определенные преимущества в скорости индексации и pr блога.

Естественно, у платформы “специально для блогов” должно быть куча готовых решений. В принципе так и есть, но на все у меня, как всегда, не хватит ни сил, ни терпения, поэтому в обзор войдет только те, которые обновлялись не поздней чем месяц назад.

Итак, 3 pluggable приложения на django для создания блога:

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


Запускаем тестовый сервер, радуемся.

image

Скрин 1 – главная страница basic_blog’а

image

Скрин 2 – Админка basic_blog’а

Идем в пункт админки Entries и добавляем новый пост – ссылка Add entry.

image

Скрин 3 – Пункт админки “Создание нового поста” в basic_blog’а

Не густо. Одна надежда на пунктик “Advanced options”, который по умолчанию свернут. Жмем.

image

Скрин 4 – Подпункт “Advanced options” в пункте админки “Создание нового поста” в basic_blog’а, в доме который построил Джек.

Оказывается, тут скрывалась опция разметки для поста. Кстати наличие тут textile, например, не связано с наличием  Python textile library у вас на компе. Теперь, кстати есть смысл ещё раз посмотреть на пункт админки “Entries”.

image

Скрин 5 – Пункт админки Entries в basic_blog’а

Комментарии излишни.

Главная страница блога теперь выглядит так:

image

Скрин 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 и обнаруживаем, что оно уже подключено!

image

Скрин 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 – лично я на этом спекся (итак ясно, что получится, так зачем время тратить).

Процесс подключения комментарием очень похож на процесс подключения тэгов.

  1. Добавляем ‘django.contrib.comments’ в INSTALLED_APPS
  2. Добавляем в 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 и можно смотреть что получилось:

image

Скрин 8 – Админка django-basic-apps.blog

image image

Скрин 9 – Добавление поста django-basic-apps.blog

Теперь главная страница блога выглядит так:

image Скрин 10 – главная страница блога django-basic-apps.blog

Страница поста открываться отказывалась, пока я не прописал в шаблоне django-basic-apps\basic\blog\templates\blog

{% load markup %}

Однако, после добавления оной заработали комменты:

image

Скрин 11 – страница комментирования поста в блоге django-basic-apps.blog

Заключение

Честно говоря, на данном этапе продолжать изучать django-basic-apps.blog уже не хочется, слишком уж сильно он завязан на остальных basic-apps, а удовольствие от его использования получить можно только в том случае, если использовать его как компонент pinax’а. Писать про pinax хочется ещё меньше, так как это отдельная большая задача.

 

Полезные ссылки:

  1. Серия статей о создании блога Ross’а Poulton’а: часть 1, часть 2, часть 3.
  2. 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