2011-12-14 7 views
2

Я хочу предоставить rss-канал под движком google/python.Создание RSS-канала в Google App Engine

Я пытался использовать обычный обработчик запросов и генерировать xml-ответ. Когда я получить доступ к URL канала напрямую, я могу видеть корм правильно, однако, когда я пытаюсь подписаться на канал в читателя Google, он говорит, что

'Подача запрашиваются не может быть найден.

Интересно, правильно ли этот подход. Я рассматривал возможность использования статического xml-файла и обновления его с помощью заданий cron. Но в то время как GAE не поддерживает файл ввода/вывода, этот подход, похоже, не сработает.

Как это решить? Благодаря!

+1

Мое предположение, вероятно, вам нужно установить правильный тип содержимого в заголовках ответов, чтобы браузер распознал его как RSS-канал. но сейчас я слишком ленив, чтобы посмотреть, какой тип контента должен дать вам официальный ответ. –

ответ

6

Там уже 2 решения, которые я предлагаю:

  1. GAE-REST вы можете просто добавить в свой проект и настроить, и это сделает RSS для вас, но проект стар и больше не поддерживается.

  2. ли как я, использовать шаблон, чтобы написать список и как это я мог бы добиться успеха, генерирующий RSS (GeoRSS), который может быть считан с помощью считывателя Google, где шаблон:

    <title>{{host}}</title> 
    <link href="http://{{host}}" rel="self"/> 
    <id>http://{{host}}/</id> 
    <updated>2011-09-17T08:14:49.875423Z</updated> 
    <generator uri="http://{{host}}/">{{host}}</generator> 
    
    {% for entity in entities %} 
    
    <entry> 
    
    <title><![CDATA[{{entity.title}}]]></title> 
    <link href="http://{{host}}/vi/{{entity.key.id}}"/> 
    <id>http://{{host}}/vi/{{entity.key.id}}</id> 
    <updated>{{entity.modified.isoformat}}Z</updated> 
    <author><name>{{entity.title|escape}}</name></author> 
    <georss:point>{{entity.geopt.lon|floatformat:2}},{{entity.geopt.lat|floatformat:2}}</georss:point> 
    <published>{{entity.added}}</published> 
    <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml">{{entity.text|escape}}</div> 
    </summary> 
    
    </entry> 
    
    {% endfor %} 
    
    </feed> 
    

Мой обработчик (вы также можете сделать это с помощью Python 2.7, как только функцию вне обработчика для более минимального решения):

class GeoRSS(webapp2.RequestHandler): 

    def get(self): 
     start = datetime.datetime.now() - timedelta(days=60) 
     count = (int(self.request.get('count' 
       )) if not self.request.get('count') == '' else 1000) 
     try: 
      entities = memcache.get('entities') 
     except KeyError: 
      entity = Entity.all().filter('modified >', 
            start).filter('published =', 
        True).order('-modified').fetch(count) 
     memcache.set('entities', entities) 
     template_values = {'entities': entities, 'request': self.request, 
          'host': os.environ.get('HTTP_HOST', 
          os.environ['SERVER_NAME'])} 
     dispatch = 'templates/georss.html' 
     path = os.path.join(os.path.dirname(__file__), dispatch) 
     output = template.render(path, template_values) 
     self.response.headers['Cache-Control'] = 'public,max-age=%s' \ 
      % 86400 
     self.response.headers['Content-Type'] = 'application/rss+xml' 
     self.response.out.write(output) 

Я надеюсь, что некоторые из этих работ для вас, оба способа работают для меня.

+1

Спасибо! Настройка типа содержимого работает! – tagtraum

2

У меня есть генератор Atom для моего блога, который работает на AppEngine/Python. Я использую механизм шаблонов Django 1.2 для создания фида. Мой шаблон выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" 
     xml:lang="en" 
     xml:base="http://www.example.org"> 
    <id>urn:uuid:4FC292A4-C69C-4126-A9E5-4C65B6566E05</id> 
    <title>Adam Crossland's Blog</title> 
    <subtitle>opinions and rants on software and...things</subtitle> 
    <updated>{{ updated }}</updated> 
    <author> 
    <name>Adam Crossland</name> 
    <email>[email protected]</email> 
    </author> 
    <link href="http://blog.adamcrossland.net/" /> 
    <link rel="self" href="http://blog.adamcrossland.net/home/feed" /> 
    {% for each_post in posts %}{{ each_post.to_atom|safe }} 
    {% endfor %} 
</feed> 

Примечание: если вы используете какой-либо из этого, вам нужно создать свой собственный UUID, чтобы пойти в ид узла.

Обновленный узел должен содержать время и дату последнего обновления содержимого фида в формате rfc 3339. К счастью, у Python есть библиотека, которая позаботится об этом для вас. Отрывок из контроллера, который генерирует канал:

from rfc3339 import rfc3339 

    posts = Post.get_all_posts() 
    self.context['posts'] = posts 

    # Initially, we'll assume that there are no posts in the blog and provide 
    # an empty date. 
    self.context['updated'] = "" 

    if posts is not None and len(posts) > 0: 
     # But there are posts, so we will pick the most recent one to get a good 
     # value for updated. 
     self.context['updated'] = rfc3339(posts[0].updated(), utc=True) 

    response.content_type = "application/atom+xml" 

Не беспокойтесь о self.context['updated'] вещи. Это то, как моя инфраструктура обеспечивает ярлык для установки переменных шаблона. Часть импорта состоит в том, что я кодирую дату, которую я хочу использовать с функцией rfc3339. Кроме того, я установил свойство content_type объекта Response равным application/atom+xml.

Единственный недостающий элемент в том, что шаблон использует метод, называемый to_atom превратить Post объект в Atom-отформатированных данных:

def to_atom(self): 
    "Create an ATOM entry block to represent this Post." 

    from rfc3339 import rfc3339 

    url_for = self.url_for() 
    atom_out = "<entry>\n\t<title>%s</title>\n\t<link href=\"http://blog.adamcrossland.net/%s\" />\n\t<id>%s</id>\n\t<summary>%s</summary>\n\t<updated>%s</updated>\n </entry>" % (self.title, url_for, self.slug_text, self.summary_for(), rfc3339(self.updated(), utc=True)) 

    return atom_out 

Это все, что требуется, насколько я знаю, и этот код действительно создает отлично-хороший и рабочий канал для моего блога. Теперь, если вы действительно хотите использовать RSS вместо Atom, вам нужно будет изменить формат шаблона подачи, шаблон Post и content_type, но я думаю, что это суть того, что вам нужно сделать, чтобы получить фид созданный приложением AppEngine/Python.

+0

Спасибо! Это очень полезно! – tagtraum

2

Нет ничего особенного в создании XML, а не в HTML, если вы правильно задали тип контента. Передайте свой канал в валидатор по адресу http://validator.w3.org/feed/, и он расскажет вам, что с ним не так.

Если это не поможет, вам нужно указать нам свой источник - мы не можем отлаживать ваш код для вас, если вы его нам не покажете.

+0

Спасибо! Настройка типа содержимого работает! – tagtraum