sitemap.xml の
即時(のような
何かいいのが
とか、
pubsubhubbub で
pubsubhubbub の
pubsubhubbub とは ?
以下の
mezzanine での pubsubhubbub
mezzanine の
pubsubhubbub 形式 での
なので、
標準で
rss、
※1. blog モジュールを
※2. カテゴリごとの
どう実装したか?
作った もの 一式
作った
Pypi にも
pip install mezzanine_pubsubhubbub_pub
フォルダ配下の
以下説明を
init.py
あまり、
参考に
package配下の
get_feed_url_patterns
feed url pattern を返します。
mezzanine.blog に依存し、 その feed url を 上書きする ため、
インストールされていれば、url を includeし、
末インストールなら、空の url pattren を 返すようにしました。
from django.conf import settings
ではなく、
from mezzanine.conf import settings
を使うように していますが、
これは、mezzanine の settings でないと、 defaluts.py で 登録した 設定値が 見えなかったりした ためです。
mezzanine のplugin 書く 且つ、 defaluts.py を 使う 場合は、
mezzanine のsettings を 使った ほうが トラブルが なくてよさそうです。 def get_feed_url_patterns(): """ Returns feed url patterns if mezzanine.blog is installed. You must call this method before include("mezzanine.urls") """ from mezzanine.conf import settings from django.conf.urls import include, url blog_installed = "mezzanine.blog" in settings.INSTALLED_APPS if blog_installed: BLOG_SLUG = settings.BLOG_SLUG.rstrip("/") if BLOG_SLUG: BLOG_SLUG += "/" feed_url_patterns = [ url("^%s" % BLOG_SLUG, include("mezzanine_pubsubhubbub_pub.urls")), ] return feed_url_patterns else: return []
ping_hub
django-push から拝借しました。
ほぼ、from django.conf import settings
を
from mezzanine.conf import settings
に変えただけです。
def ping_hub(feed_url, hub_url=None): """ Makes a POST request to the hub. If no hub_url is provided, the value is fetched from the PUSH_HUB setting. Returns a dictionary with `requests.models.Response` object to the value """ from mezzanine.conf import settings if hub_url is None: hub_url = getattr(settings, 'PUSH_HUB', None) if hub_url is None: raise ValueError("Specify hub_url or set the PUSH_HUB setting.") params = { 'hub.mode': 'publish', 'hub.url': feed_url, } results = {} for elem in hub_url: result = requests.post(elem, data=params, headers={'User-Agent': UA}) results.update({elem: result}) return results
defaults.py
設定値のみ
PUSH_HUB
通知先のHUBサーバーの URLを 指定します。
Tapleで複数指定可能です。
複数指定時は、rss feed 、 atom feed に hub url が 複数追加されます。
当初は、editable=True
で指定していましたが、
管理画面からTapleの 編集が うまくできなかったため、
editable=False
としています。
何かうまいやり方があるのかもしれませんが、 見つけられませんでした。 PUSH_URL_PROTOCOL
HUBサーバーに通知する Feed URL の プロトロルを 指定します。
サイトに よっては HTTP/HTTPS双方で 送る ケースも あるかもしれないので、
BOTH
も設定可能です。
choices=PROTOCOL_TYPE_CHOICES,
でTapleを 設定可能で、
editable=True,
にして おくと、 管理画面上以下のように、 出力されます。 管理画面
feeds.py
feeds.py も
も
rss の
タグがatom:link
と
- HubRss201rev2Feed
class HubRss201rev2Feed(Rss201rev2Feed): def add_root_elements(self, handler): super(Rss201rev2Feed, self).add_root_elements(handler) hub = self.feed.get('hub') if hub is not None: for elem in hub: handler.addQuickElement('atom:link', '', {'rel': 'hub', 'href': elem})
models.py
models.py と
mezzanine で
signal を
HubBlogPost で
signal 登録しているのは、
ModelMixin で
管理画面から
extra_model_fields でも
今回の
class HubBlogPost(ModelMixin): class Meta: mixin_for = BlogPost def notify_blog_post(sender, instance, **kwargs): if instance.status == CONTENT_STATUS_PUBLISHED: site = Site.objects.get(id=current_site_id()) protocol_type = getattr(settings, 'PUSH_URL_PROTOCOL', None) if protocol_type == PROTOCOL_TYPE_HTTP: __ping_hub_http(site) elif protocol_type == PROTOCOL_TYPE_HTTPS: __ping_hub_https(site) elif protocol_type == PROTOCOL_TYPE_BOTH: __ping_hub_http(site) __ping_hub_https(site) else: raise ValueError("PUSH_URL_PROTOCOL is None...") post_save.connect(notify_blog_post, sender=HubBlogPost)
urls.py
mezzanine/urls.py at master · stephenmcd/mezzanine から、
feed url の
mezzanine の
# Trailing slahes for urlpatterns based on setup. _slash = "/" if settings.APPEND_SLASH else "" # Blog patterns. urlpatterns = [ url("^feeds/(?P<format>.*)%s$" % _slash, views.blog_post_feed, name="blog_post_feed"), url("^tag/(?P<tag>.*)/feeds/(?P<format>.*)%s$" % _slash, views.blog_post_feed, name="blog_post_feed_tag"), ]
views.py
こちらも、
mezzanine/views.py at master · stephenmcd/mezzanine から、
部分抜粋して
views.py の
from mezzanine_pubsubhubbub_pub.feeds import HubPostsRSS, HubPostsAtom def blog_post_feed(request, format, **kwargs): """ Blog posts feeds - maps format to the correct feed view. """ try: return {"rss": HubPostsRSS, "atom": HubPostsAtom}[format](**kwargs)(request) except KeyError: raise Http404()
クイックスタート
Github上の、
※ 是非、
実際に 効果が あるのか ?
いや、
そもそも
投稿して
Sitemap送信よりは
Pypi に
送ってるにしろそもそもの
Google Admin Console で
その他Tips
テスト時に
mezzanine.utils.tests.TestCase に ついて
django.test.TestCase と
mezzanine の
以下のような
class PagesTests(TestCase): def setUp(self): """ Make sure we have a thread-local request with a site_id attribute set. """ super(PagesTests, self).setUp() from mezzanine.core.request import _thread_local request = self._request_factory.get('/') request.site_id = settings.SITE_ID _thread_local.request = request
_thread_local.request = request
みたいな
tests.py を
File "/Library/Python/2.7/site-packages/mezzanine/blog/feeds.py", line 68, in add_domain return add_domain(self._site.domain, link, self._request.is_secure()) AttributeError: 'NoneType' object has no attribute 'is_secure'
どうもcurrent_request()
と
この
_thread_local.request = request
で
current_request()
で
xml.etree.ElementTree を 使っていて atom:link タグが 取得できなかった
test をatom:link
タグが
root = ET.fromstringlist(response._container) elems = root.findall(".//atom:link")
root = ET.fromstringlist(response._container) elems = root.findall(".//link")
と書いてみたりしていましたが、
root = ET.fromstringlist(response._container) elems = root.findall(".//{http://www.w3.org/2005/Atom}link")
で取得できるようです。
:
は
@patch.object を 使う際は、 テストメソッドに 第2引数が 必要に なる。
テストケースを
@patch.object(requests, "post", side_effect=mocked_requests_post) def test_feed_atom(self): resolver_match = resolve('/blog/feeds/atom/') blog_post_feed = resolver_match.func # Create an instance of a GET request. from mezzanine.core.request import _thread_local request = self._request_factory.get('/blog/feeds/atom/') request.site_id = settings.SITE_ID _thread_local.request = request response = blog_post_feed(request, format=resolver_match.kwargs['format']) import xml.etree.ElementTree as ET root = ET.fromstringlist(response._container) elem = root.find("{http://www.w3.org/2005/Atom}link") self.assertEqual('hub', elem.attrib['rel']) self.assertEqual('https://pubsubhubbub.appspot.com/', elem.attrib['href'])
エラーとなりました。
====================================================================== ERROR: test_feed_atom (tests.tests.BlogPostFeedTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Library/Python/2.7/site-packages/mock/mock.py", line 1305, in patched return func(*args, **keywargs) TypeError: test_feed_atom() takes exactly 1 argument (2 given)
@patch.object のように、
以下のように
@patch.object(requests, "post", side_effect=mocked_requests_post) def test_feed_atom(self, mock_post): resolver_match = resolve('/blog/feeds/atom/') blog_post_feed = resolver_match.func # Create an instance of a GET request. from mezzanine.core.request import _thread_local request = self._request_factory.get('/blog/feeds/atom/') request.site_id = settings.SITE_ID _thread_local.request = request response = blog_post_feed(request, format=resolver_match.kwargs['format']) import xml.etree.ElementTree as ET root = ET.fromstringlist(response._container) elem = root.find("{http://www.w3.org/2005/Atom}link") self.assertEqual('hub', elem.attrib['rel']) self.assertEqual('https://pubsubhubbub.appspot.com/', elem.attrib['href'])
実装時に 参考に した サイト
長くなりましたが、
以上です。
コメント