在Django中提及/内部链接

时间:2014-11-02 19:12:33

标签: python django django-templates django-views

我有一堆模特。所有这些模型都有方法get_absolute_url和字段text。我想在text字段中创建内部链接,就像维基百科一样。

维基百科在页面中的内部链接仅指其他页面。我需要链接到我的所有模型。

我可以为内部链接创建一个模式,并用硬编码的url替换这个模式到一个url,但它确实不是一个好主意,因为链接可以改变。所以我最好能参考get_absolute_url

另一种选择是使用模板标签将特定模式更改为链接。

应该怎么做?是否有任何已经完成此项目的开源项目?

1 个答案:

答案 0 :(得分:2)

我想在几天前回答同样的问题,我用模板过滤器做了。我的链接是相对的URL,不是绝对的,但你可以很容易地调整它,你也可以调整正则表达式模式以匹配你喜欢的任何链接标记。

使用过滤器时,只会在显示时查看链接,因此,如果您的视图的网址已更改,则应使用reverse()查找自动更新。

我还使用Markdown来处理我的描述字段,所以我让链接返回一个markdown格式的链接而不是HTML,但你也可以调整它。如果您使用Markdown,则需要先放置此过滤器。

因此,为了显示带有内部链接的TextField描述,在模板中将是这样的:

{{ entity.description|internal_links|markdown }}

(有关编写和注册过滤器的详细信息,请参阅Django docs on writing your own custom filters。)

至于具体的过滤器本身,我是这样做的:

from django import template
from django.core.urlresolvers import reverse
from my.views import *

register = template.Library()

@register.filter
def internal_links(value):
    """
    Takes a markdown textfield, and filters
    for internal links in the format:

    {{film:alien-1979}}

    ...where "film" is the designation for a link type (model),
    and "alien-1979" is the slug for a given object

    NOTE: Process BEFORE markdown, as it will resolve
    to a markdown-formatted linked name:

    [Alien](http://opticalpodcast.com/cinedex/film/alien-1979/)

    :param value:
    :return:
    """
    try:
        import re
        pattern = '{{\S+:\S+}}'
        p = re.compile(pattern)
        #replace the captured pattern(s) with the markdown link
        return p.sub(localurl, value)
    except:
        # If the link lookup fails, just display the original text
        return value

def localurl(match):
    string = match.group()

    # Strip off the {{ and }}
    string = string[2:-2]

    # Separate the link type and the slug
    link_type, link_slug = string.split(":")
    link_view = ''

    # figure out what view we need to display
    # for the link type
    if(link_type == 'film'):
        link_view = 'film_detail'
    elif(link_type == 'person'):
        link_view = 'person_detail'
    else:
        raise Exception("Unknown link type.")

    link_url = reverse(link_view, args=(link_slug,))
    entity = get_object_or_404(Entity, slug=link_slug)
    markdown_link = "[" + entity.name + "](" + link_url + ")"

    return markdown_link