3

私は Django Feeds Framework を使用していますが、これは非常に素晴らしく、非常に直感的で使いやすいものです。ただし、HTML でフィードへのリンクを作成する場合に問題があると思います。

例えば:

<link rel="alternate" type="application/rss+xml" title="{{ feed_title }}" href="{{ url_of_feed }}" />

リンクのHREF属性は簡単に見つけることができます。使用するだけですreverse()

しかし、TITLE属性はどうですか?テンプレート エンジンはこれをどこで探すべきですか? さらに、フィードが動的に構築され、タイトルがパラメーターに依存する場合 (こののように) はどうなるでしょうか?

私には「DRY」と思われる解決策を思いつくことができません...私が思いつくことができるのは、コンテキストプロセッサまたはテンプレートタグを使用することだけですが、コンテキストプロセッサ/テンプレートタグがパラメーターを見つけなければならない場合、面倒になりますFeed クラスを構築し、これを書いていると、ビュー内で Feed インスタンスを自分で作成する方法さえ知らないことに気付きました。

このロジックをすべてビューに入れると、1 つのビューだけではなくなります。また、 の値TITLEはビューとフィードにあります。

4

2 に答える 2

0

推測にすぎませんが (私の django アプリではまだフィードを使用していないため)、フィード オブジェクトに特別な template_context をフィード オブジェクトに追加し、それを base.html で使用することができます。

于 2010-05-06T22:30:11.627 に答える
0

私はこの解決策に完全に満足していませんRequest.魔法の方法を使用してフィードを壊す可能性があります. そこに行きます:

#coding:utf-8
# Author: Armando Pérez Marqués <mandx@rbol.org>
# Purpose: Django TemplateTag to output feed links in templates in a DRY way
# Created: 05/07/2010

import re

from django import template
from django.conf import settings
from django.contrib.syndication.views import Feed
from django.core.urlresolvers import reverse, resolve, NoReverseMatch
from django.template import Node
from django.template import TemplateSyntaxError
from django.utils.encoding import smart_str
from django.utils.html import escape as html_escape
from django.utils.safestring import mark_safe

register = template.Library()

kwarg_re = re.compile(r"(?:(\w+)=)?(.+)")

class FeedInfoNode(Node):
    def __init__(self, view_name, args, kwargs, asvar):
        self.view_name = view_name
        self.args = args
        self.kwargs = kwargs
        self.asvar = asvar

    def render(self, context):
        args = [arg.resolve(context) for arg in self.args]
        kwargs = dict([(smart_str(k,'ascii'), v.resolve(context))
                       for k, v in self.kwargs.items()])

        # Try to look up the URL twice: once given the view name, and again
        # relative to what we guess is the "main" app. If they both fail,
        # re-raise the NoReverseMatch unless we're using the
        # {% feed_info ... as var %} construct in which cause return nothing.
        url = ''
        try:
            url = reverse(self.view_name, args=args, kwargs=kwargs, current_app=context.current_app)
        except NoReverseMatch, e:
            if settings.SETTINGS_MODULE:
                project_name = settings.SETTINGS_MODULE.split('.')[0]
                try:
                    url = reverse(project_name + '.' + self.view_name,
                              args=args, kwargs=kwargs, current_app=context.current_app)
                except NoReverseMatch:
                    if self.asvar is None:
                        # Re-raise the original exception, not the one with
                        # the path relative to the project. This makes a
                        # better error message.
                        raise e
            else:
                if self.asvar is None:
                    raise e

        if 'request' in context:
            request = context['request']
        else:
            request = None

        feed_instance, feed_args, feed_kwargs = resolve(url)
        if not isinstance(feed_instance, Feed):
            raise NoReverseMatch, \
                  'feed_info can only reverse class-based feeds'

        feed_obj = feed_instance.get_object(request, *feed_args, **feed_kwargs)

        feed_data = {
            'url': url,
            'obj': feed_instance,
            'args': feed_args,
            'kwargs': feed_kwargs,
            #'title': html_escape(feed_instance.__get_dynamic_attr('title', obj)),
            'title': html_escape(
                feed_instance._Feed__get_dynamic_attr('title', feed_obj)
                ),
            'type': feed_instance.feed_type.mime_type,
        }

        if self.asvar:
            context[self.asvar] = feed_data
            return ''
        else:
            return mark_safe(
                '<link rel="alternate" type="%(type)s" title="%(title)s" href="%(url)s" />' \
                % feed_data
            )

def feed_info(parser, token):
    """
    Returns an mapping containing populated info about the reversed feed
    Works exactly as the url tag, but the mapping is not returned, instead
    a variable is always set  in the context.

    This is a way to define links that aren't tied to a particular URL
    configuration::

        {% feed_info path.to.some_feed_view_class arg1 arg2 as feed_info_var %}

        or

        {% feed_info path.to.some_feed_view_class name1=value1 name2=value2 as feed_info_var %}
    """

    bits = token.split_contents()
    if len(bits) < 2:
        raise TemplateSyntaxError("'%s' takes at least one argument"
                                  " (path to a feed view)" % bits[0])
    viewname = bits[1]
    args = []
    kwargs = {}
    asvar = None
    bits = bits[2:]
    if len(bits) >= 2 and bits[-2] == 'as':
        asvar = bits[-1]
        bits = bits[:-2]

    # Backwards compatibility: check for the old comma separated format
    # {% url urlname arg1,arg2 %}
    # Initial check - that the first space separated bit has a comma in it
    if bits and ',' in bits[0]:
        check_old_format = True
        # In order to *really* be old format, there must be a comma
        # in *every* space separated bit, except the last.
        for bit in bits[1:-1]:
            if ',' not in bit:
                # No comma in this bit. Either the comma we found
                # in bit 1 was a false positive (e.g., comma in a string),
                # or there is a syntax problem with missing commas
                check_old_format = False
                break
    else:
        # No comma found - must be new format.
        check_old_format = False

    if check_old_format:
        # Confirm that this is old format by trying to parse the first
        # argument. An exception will be raised if the comma is
        # unexpected (i.e. outside of a static string).
        match = kwarg_re.match(bits[0])
        if match:
            value = match.groups()[1]
            try:
                parser.compile_filter(value)
            except TemplateSyntaxError:
                bits = ''.join(bits).split(',')

    # Now all the bits are parsed into new format,
    # process them as template vars
    if len(bits):
        for bit in bits:
            match = kwarg_re.match(bit)
            if not match:
                raise TemplateSyntaxError("Malformed arguments to url tag")
            name, value = match.groups()
            if name:
                kwargs[name] = parser.compile_filter(value)
            else:
                args.append(parser.compile_filter(value))

    return FeedInfoNode(viewname, args, kwargs, asvar)

feed_info = register.tag(feed_info)

テンプレート タグのコードから始めて{% url %}、フィードの URL を取得した後、これを使用resolve()して Feed サブクラス インスタンスを取得し、必要な属性を取得します。

注意事項

  • Django 1.2 クラス フィードが必要です。フィードの古い方法でこれを行う方法が正確にはわかりません。
  • フィード クラスが request オブジェクトを使用する場合、コンテキスト プロセッサがコンテキストに存在しない場合に渡されるため、request コンテキスト プロセッサを構成する必要があります。None
  • Feed.__get_dynamic_attr() には奇妙な点があります。Feed サブクラスのインスタンスにはこのメソッドがありません。代わりに、別の名前で表示されます。実行時に名前を理解する方法がわかりません...
于 2010-05-08T02:34:01.727 に答える