Главная | Архив новостей | Общение | Площадка | Примеры OpenID
Хостинг Django от «Джино»
Оглавление

Средства трансляции

Django поставляется со средствами высокого уровня для трансляции данных, что позволяет легко создавать потоки RSS или Atom.

Что такое RSS? Что такое Atom?

RSS и Atom оба являются форматами, базирующимися на XML, которые вы можете использовать для рассылки автоматически обновляемого «содержания» для вашего сайта. Более подробно об RSS можно узнать на http://www.whatisrss.com/, об Atom — на http://www.atomenabled.org/.

Здесь и далее мы будем использовать термин «трансляция» для английской фразы «syndication feed».

Для создания любой трансляции вам понадобится только написать короткий класс на языке Python. Вы можете создавать столько трансляций, сколько требуется.

Средой высокого уровня для генерации трансляций является представление, которое по договорённости подключено к /feeds/. Django использует хвостовую часть URL (то, что идёт после /feeds/) для определения того, какую именно трансляцию следует вернуть.

Для создания трансляции, вам потребуется написать класс Feed и указать на него в вашем файле привязок URL (обратитесь к главам «Представления и привязки URL» и «Усовершенствованные представления и схемы URL» для подробностей).

Инициализация

Чтобы активировать трансляции на вашем сайте, добавьте следующее в файл привязок:

(r'^feeds/(?P<url>.*)/$',
 'django.contrib.syndication.views.feed',
 {'feed_dict': feeds}
),

Этот код указывает Django, что следует использовать RSS среду для обработки всех URL, которые начинаются с feeds/. (Вы можете изменить этот префикс feeds/ на любой необходимый.)

Следует отметить, что параметр feed_dict должен быть словарём, который совпадает с сокращением для трансляции (метка для короткого URL). Вы можете определить этот параметр в файле привязок. Ниже дан полный пример:

from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory

feeds = {
    'latest': LatestEntries,
    'categories': LatestEntriesByCategory,
}

urlpatterns = patterns('',
    # ...
    (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
        {'feed_dict': feeds}),
    # ...
)

Вышеприведённый пример регистрирует две трансляции:

  • Трансляция, представленная LatestEntries, будет жить на feeds/latest/.

  • Трансляция, представленная LatestEntriesByCategory, будет жить на feeds/categories/.

Теперь надо определить сами классы Feed.

Класс Feed является обычным классом Python и представляет собой класс трансляции. Трансляция может быть простой (т.е. отображающей новости сайта или последние записи блога) или более сложной (т.е. отображающей все записи блога в определённой категории, где категория является переменной).

Вы должны подключать в код представления класс django.contrib.syndication.feeds.Feed. Классы Feed могут располагаться в любой точке вашего кода.

Простая трансляция

Этот простой пример, взятый с http://chicagocrime.org/, описывает трансляцию, которая возвращает пять свежих новостей:

from django.contrib.syndication.feeds import Feed
from chicagocrime.models import NewsItem

class LatestEntries(Feed):
    title = "Chicagocrime.org site news"
    link = "/sitenews/"
    description = "Updates on changes and additions to chicagocrime.org."

    def items(self):
        return NewsItem.objects.order_by('-pub_date')[:5]

Отметим важные аспекты этого кода:

  • Класс подключает django.contrib.syndication.feeds.Feed.

  • Атрибуты title, link и description соответствуют стандартным элементам RSS: <title>, <link> и <description>.

  • Метод items() возвращает список объектов, которые должны быть включены в трансляцию в виде элементов <item>. Несмотря на то, что этот пример возвращает объекты NewsItem с помощью API для работы с базой данных, метод items() не обязан возвращать экземпляры модели.

    Вы «бесплатно» получаете некоторую функциональность, используя модели Django, но метод items() может вернут любой тип объекта.

Надо сделать ещё кое-что. В RSS-потоке каждый элемент <item> имеет элементы <title>, <link> и <description>. Необходимо указать среде какие именно данные следует помещать в эти элементы.

  • Чтобы указать содержимое для <title> и <description>, создайте шаблоны (см. главу «Шаблоны») с именами feeds/latest_title.html и feeds/latest_description.html, где latest является сокращением, которое указано в файле привязки для конкретной трансляции. Следует отметить, что наличие расширения .html обязательно.

    Система RSS обрабатывает этот шаблон для каждого элемента, передавая ему две контекстные переменные:

    • obj: текущий объект (один из объектов полученных от метода items()).

    • site: Объект класса django.models.core.sites.Site, представляющий текущий сайт. Полезен для {{ site.domain }} или {{ site.name }}.

    Если вы не создадите шаблон хотя бы для одного элемента, среда будет использовать шаблон {{ obj }} по умолчанию, т.е. обычное текстовое представление объекта.

    Также вы можете поменять имена этих двух шаблонов, определив атрибуты title_template и description_template для класса Feed.

  • При определении содержимого для <link> у вас есть две опции. Для каждого элемента, возвращённого методом items(), Django сначала пытается выполнить его метод get_absolute_url(). Если такого метода нет у объекта, Django пытается вызвать метод item_link() для класса Feed, передавая ему один параметр item, который является этим объектом.

    Оба метода, get_absolute_url() и item_link(), должны возвращать URL элемента в виде обычной строки Python.

  • Для показанного ранее примера LatestEntries мы можем создать очень простые шаблоны:

    # latest_title.html
    {{ obj.title }}
    
    #latest_description.html
    {{ obj.description }}
    

    Это всегда слишком просто ...

Более сложная трансляция

Сайт http://chicagocrime.org предоставляет RSS-потоки по последним преступлениям для каждого полицейского участка в Чикаго. Можно устать, создавая классы Feed для каждого участка. Это нарушит принцип DRY и приведёт к размещению данных в логике программы.

Вместо этого, среда трансляций позволяет вам создать базовые трансляции, которые возвращают элементы в зависимости от URL.

На нашем сайте трансляции для полицейских участков доступны через URL, подобные этим:

Здесь сокращением является beats. Среда трансляций обнаруживает хвостовую часть URL после beats — 0613 и 1424 — и предоставляет вам возможность указать ей, что означает эта дополнительная часть URL и как она влияет на транслируемые данные.

Пример должен всё прояснить. Ниже представлен код для таких трансляций:

from django.core.exceptions import ObjectDoesNotExist

class BeatFeed(Feed):
    def get_object(self, bits):
        # In case of "/rss/beats/0613/foo/bar/baz/", or other such
        # clutter, check that bits has only one member.
        if len(bits) != 1:
            raise ObjectDoesNotExist
        return Beat.objects.get(beat__exact=bits[0])

    def title(self, obj):
        return "Chicagocrime.org: Crimes for beat %s" % obj.beat

    def link(self, obj):
        return obj.get_absolute_url()

    def description(self, obj):
        return "Crimes recently reported in police beat %s" % obj.beat

    def items(self, obj):
        crimes =  Crime.objects.filter(beat__id__exact=obj.id)
        return crimes.order_by('-crime_date')[:30]

Здесь представлен базовый алгоритм среды RSS-потоков. Берём данный класс и обрабатываем URL /rss/beats/0613/:

  1. Среда трансляций получает URL /rss/beats/0613/ и отмечает, что существует дополнительная часть данных в URL. Среда отделяет эту часть по символу / и вызывает у класса Feed метод get_object(), передавая ему эту часть URL.

    В данном случае, такой частью будет ['0613']. Для запроса /rss/beats/0613/foo/bar/' — ['0613', 'foo', 'bar'].

  2. Метод get_object() отвечает за получение соответствующего участка из полученного набора.

    В данном случае, среда трансляций использует API для работы с базой данных для получения информации по указанному полицейскому участку. Следует отметить, что метод get_object() должен вызывать исключение django.core.exceptions.ObjectDoesNotExist в случае получения неверного параметра. Здесь не использована связка try / except для вызова Beat.objects.get(), т.к. в этом нет необходимости. В случае неудачи данный метод вызывает исключение Beat.DoesNotExist, которое является подклассом ObjectDoesNotExist. Вызов исключения ObjectDoesNotExist в get_object() указывает Django, что необходимы выдать страницу с ошибкой 404 на обрабатываемый запрос.

  3. Для генерации элементов <title>, <link> и <description> Django использует методы title(), link() и description(). В предыдущем примере они были простыми строковыми атрибутами класса, но данный пример иллюстрирует, что они могут быть строками или методами. Для каждого элемента title, link и description Django следует нижеприведённому алгоритму:

    1. Производится вызов метода с передачей ему аргумента obj, где obj является объектом, возвращённым методом get_object().

    2. В случае неудачи, производится вызов метода без аргументов.

    3. В случае неудачи, используется атрибут класса.

  4. Следует отметить, что items() в данном примере также принимает аргумент obj. Алгоритм для items полностью совпадает с предыдущим пунктом — сначала производится вызов items(obj), затем items() и наконец используется атрибут класса items (который должен быть списком).

Полная документация по всем методам и атрибутам классов Feed доступна на официальном сайте Django (http://www.djangoproject.com/documentation/0.96/syndication_feeds/).

Указание типа трансляции

По умолчанию среда трансляций генерирует RSS 2.0. Для изменения этого поведения надо добавить атрибут feed_type в ваш класс Feed:

from django.utils.feedgenerator import Atom1Feed

class MyFeed(Feed):
    feed_type = Atom1Feed

Следует отметить то, что вы устанавливаете этот атрибут для класса, а не для экземпляра. Доступные типы трансляций показаны в таблице «Типы трансляций»:

Таблица 11.1. Типы трансляций

Класс трансляцииФормат
django.utils.feedgenerator.Rss201rev2Feed RSS 2.01 (по умолчанию)
django.utils.feedgenerator.RssUserland091Feed RSS 0.91
django.utils.feedgenerator.Atom1Feed Atom 1.0


Вложения

Для того, чтобы указать вложения (т.е. медиа ресурсы ассоциированные с элементами трансляции, такими как MP3 подкасты), используйте обработчики item_enclosure_url, item_enclosure_length и item_enclosure_mime_type, например:

from myproject.models import Song

class MyFeedWithEnclosures(Feed):
    title = "Example feed with enclosures"
    link = "/feeds/example-with-enclosures/"

    def items(self):
        return Song.objects.all()[:30]

    def item_enclosure_url(self, item):
        return item.song_url

    def item_enclosure_length(self, item):
        return item.song_length

    item_enclosure_mime_type = "audio/mpeg"

Это предполагает, что вы уже создали объект Song с полями song_url и song_length (размер в байтах).

Язык

Трансляции создаваемые средой автоматически получают соответствующий тег <language> (RSS 2.0) или атрибут xml:lang (Atom). Значение этого тега зависит от параметра конфигурации LANGUAGE_CODE.

URL

Атрибут/метод link может возвращать как абсолютный URL (т.е. /blog/), так и полный URL (т.е. http://www.example.com/blog/). Если link не возвратил домен, то среда трансляций добавит домен текущего сайта в соответствии с параметром конфигурации SITE_ID.

Трансляции Atom требуют наличия <link rel="self">, который определяет место расположения трансляции. Среда трансляций создаёт его автоматически, используя домен текущего сайта в соответствии с параметром конфигурации SITE_ID.

Одновременная трансляция Atom и RSS

Некоторые разработчики предпочитают предоставлять трансляции в обоих видах: RSS и Atom. С помощью Django это несложно сделать: просто создайте подкласс для вашего класса feed и установите feed_type в что-нибудь отличное. Затем добавьте его вызов в ваш файл привязок. Вот полный пример:

from django.contrib.syndication.feeds import Feed
from chicagocrime.models import NewsItem
from django.utils.feedgenerator import Atom1Feed

class RssSiteNewsFeed(Feed):
    title = "Chicagocrime.org site news"
    link = "/sitenews/"
    description = "Updates on changes and additions to chicagocrime.org."

    def items(self):
        return NewsItem.objects.order_by('-pub_date')[:5]

class AtomSiteNewsFeed(RssSiteNewsFeed):
    feed_type = Atom1Feed

А здесь соответствующий файл привязок:

from django.conf.urls.defaults import *
from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed

feeds = {
    'rss': RssSiteNewsFeed,
    'atom': AtomSiteNewsFeed,
}

urlpatterns = patterns('',
    # ...
    (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
        {'feed_dict': feeds}),
    # ...
)


Увидели ошибку?
Выделите её мышкой и нажмите
Ctrl-Enter
Обработано:
1049 49 130 71

Версия книги
1.0 2.0
Версия 2.0 в процессе перевода!

Мой луч
Многообразие света

Полезное
Актуальные вакансии, Python работа для python-разработчиков.


Скачать в формате
CHM от 2 сентября

Заказать PDF файл можно через почту, чат, джаббер. Всего 2WMZ. Содержимое точно соответствует содержимому сайта.
Чем чаще заказываете — тем больше перевожу.

Русская группа

на поддержку перевода
Яндекс Яндекс.Деньги Хочу такую же кнопку
Ускорить процесс перевода!
R130494980980
Z425285133788
E112528079659
U327380922061

Книга помогла реализовать:
Проект «Мой луч»
АРМ УФМС.


Мой вебсайт стоит666 337,31 руб

© 2008-2009 Ruslan Popov @ gmail.com Powered by Django 1.1 beta 1 SVN-11114
Главная | Архив новостей | Общение | Площадка | Примеры OpenID