1 # Modified version of the {% url %} tag that allows you to specify a hostname 2 # {% hosturl http://hostpath/path path.to.some_view arg1,arg2,name1=value1 %} 3 4 from django import template 5 from django.conf import settings 6 7 register = template.Library() 8 9 class HostURLNode(template.Node): 10 def __init__(self, hostpath, view_name, args, kwargs, asvar): 11 self.hostpath = hostpath 12 self.view_name = view_name 13 self.args = args 14 self.kwargs = kwargs 15 self.asvar = asvar
1 # Modified version of the {% url %} tag that allows you to specify a hostname
2 # {% hosturl http://hostpath/path path.to.some_view arg1,arg2,name1=value1 %}
3
4 from django import template
5 from django.conf import settings
6
7 register = template.Library()
8
9 class HostURLNode(template.Node):
10 def __init__(self, hostpath, view_name, args, kwargs, asvar):
11 self.hostpath = hostpath
12 self.view_name = view_name
13 self.args = args
14 self.kwargs = kwargs
15 self.asvar = asvar
16 print self.view_name
17
18 def render(self, context):
19 from django.core.urlresolvers import reverse, NoReverseMatch
20 args = [arg.resolve(context) for arg in self.args]
21 kwargs = dict([(smart_str(k,'ascii'), v.resolve(context))
22 for k, v in self.kwargs.items()])
23
24
25 # Try to look up the URL twice: once given the view name, and again
26 # relative to what we guess is the "main" app. If they both fail,
27 # re-raise the NoReverseMatch unless we're using the
28 # {% hosturl ... as var %} construct in which cause return nothing.
29 url = ''
30 try:
31 url = reverse(self.view_name, args=args, kwargs=kwargs)
32 except NoReverseMatch:
33 project_name = settings.SETTINGS_MODULE.split('.')[0]
34 try:
35 url = reverse(project_name + '.' + self.view_name,
36 args=args, kwargs=kwargs)
37 except NoReverseMatch:
38 if self.asvar is None:
39 raise
40
41 if self.asvar:
42 context[self.asvar] = self.hostpath + url
43 return ''
44 else:
45 return self.hostpath + url
46
47 def hosturl(parser, token):
48 """
49 Returns an absolute URL matching given view with its parameters.
50
51 This is a way to define links that aren't tied to a particular URL
52 configuration::
53
54 {% hosturl hostpath path.to.some_view arg1,arg2,name1=value1 %}
55
56 The first argument is a path to a view. It can be an absolute python path
57 or just ``app_name.view_name`` without the project name if the view is
58 located inside the project. Other arguments are comma-separated values
59 that will be filled in place of positional and keyword arguments in the
60 URL. All arguments for the URL should be present.
61
62 For example if you have a view ``app_name.client`` taking client's id and
63 the corresponding line in a URLconf looks like this::
64
65 ('^client/(\d+)/$', 'app_name.client')
66
67 and this app's URLconf is included into the project's URLconf under some
68 path::
69
70 ('^clients/', include('project_name.app_name.urls'))
71
72 then in a template you can create a link for a certain client like this::
73
74 {% hosturl http://other_server/path/to app_name.client client.id %}
75
76 The URL will look like ``http://other_server/path/to/clients/client/123/``.
77 """
78 bits = token.contents.split(' ')
79 if len(bits) < 3:
80 raise TemplateSyntaxError("'%s' takes at least two arguments"
81 " (hostpath and path to a view)" % bits[0])
82 hostpath = bits[1]
83 viewname = bits[2]
84 args = []
85 kwargs = {}
86 asvar = None
87
88 if len(bits) > 3:
89 bits = iter(bits[3:])
90 for bit in bits:
91 if bit == 'as':
92 asvar = bits.next()
93 break
94 else:
95 for arg in bit.split(","):
96 if '=' in arg:
97 k, v = arg.split('=', 1)
98 k = k.strip()
99 kwargs[k] = parser.compile_filter(v)
100 elif arg:
101 args.append(parser.compile_filter(arg))
102 return HostURLNode(hostpath, viewname, args, kwargs, asvar)
103 hosturl = register.tag(hosturl)
Show all