2
I wanted to answer this same problem just a few days ago, and I did it with a template filter. My links are relative URLs, not absolute, but you could tweak that pretty easily, and you could also tweak the regex pattern to match whatever link markup you prefer.
Using the filter, the link is only looked up at display time, so if your view’s URL has changed, that should automatically update with the reverse()
lookup.
I also use Markdown to process my description fields, so I make the link return a markdown-formatted link instead of HTML, but you could tweak that too. If you use Markdown, you’d want to put this filter first.
So to display a description TextField with internal links, in the template would be something like this:
{{ entity.description|internal_links|markdown }}
(See the Django docs on writing your own custom filters for more details on writing and registering filters.)
As for the specific filter itself, I did it like this:
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