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 searches for internal links in the format: {{film:alien-1979}} ...where "film" is the designation for a model, and "alien-1979" is the slug for a given object NOTE: Process BEFORE markdown If it is inside a markdown link, it will resolve with the link text as intended: [the first Alien movie]({{film:alien-1979}}) [the first Alien movie](/cinedex/film/alien-1979/) If it is by itself, it will resolve to a linked name: {{film:alien-1979}} [Alien (1979)](/cinedex/film/alien-1979/) :param value: :return: """ try: import re # Pattern(s) inside a markdown link first # e.g. [link text here]({{film:alien-1979}}) pattern = '\[.+\]\({{\S+:\S+}}\)' p = re.compile(pattern) text_linked = p.sub(localurl_markdown, value) # After we replace those, find pattern(s) by itself # e.g. {{film:alien-1979}} pattern = '{{\S+:\S+}}' p = re.compile(pattern) #replace the captured pattern(s) with the new markdown link return p.sub(localurl, text_linked) except: # Link lookups fail individually, but just in case there's # some massive failure, just display the original text return value def localurlpattern(string): # Strip off the {{ and }} string = string[2:-2] # Separate the link type and the slug link_type, link_slug = string.split(":") # figure out what view we need to display for the link_type # Dictionary contains lookup as - link_type: viewname # "viewname can be a string containing the Python path to the view object, a URL pattern name, or the callable view object." # see https://docs.djangoproject.com/en/dev/ref/urlresolvers/#django.core.urlresolvers.reverse link_types_views = { 'film': 'film_detail', 'person': 'person_detail', 'company': 'company_detail', 'term': 'term_detail', } # TODO: Maybe add error handling for a bad link_type, and try to look it up anyway link_url = reverse(link_types_views[link_type], args=(link_slug,)) entity = get_object_or_404(Entity, slug=link_slug) if link_type == 'film': # If it's a film, the name should be in italics and include the year. link_name = "*" + entity.name + "* (" + str(entity.release_date.year) + ")" else: link_name = entity.name # Return name and link_url as part of a dictionary link_dict = {'name': link_name, 'url': link_url} return link_dict def localurl(match): string = match.group() try: link_dict = localurlpattern(string) markdown_link = "[" + link_dict['name'] + "](" + link_dict['url'] + ")" return markdown_link except: # The lookup has failed, so let's send back a notice that it's broken print('Broken internal_links localurl to ' + string) markdown_link = "[***[broken link to " + string[2:-2] + "]***](#" + string[2:-2] + ")" return markdown_link def localurl_markdown(match): string = match.group() markdown_link = "" # Grab the link text and link pattern p_obj = re.search(r'\[(.+)\]\(({{\S+:\S+}})\)', string) try: if p_obj: link_dict = localurlpattern(p_obj.group(2)) markdown_link = "[" + p_obj.group(1) + "](" + link_dict['url'] + ")" return markdown_link except: # The lookup has failed, so let's send back a notice that it's broken print('Broken internal_links localurl_markdown to ' + string) if p_obj: markdown_link = "[" + p_obj.group(1) + " ***[broken link to " + p_obj.group(2)[2:-2] + "]***](#" + p_obj.group(2)[2:-2] + ")" return markdown_link else: return string