| | 306 | class URLNode(Node): |
|---|
| | 307 | def __init__(self, view_name, args, kwargs): |
|---|
| | 308 | self.view_name = view_name |
|---|
| | 309 | self.args = args |
|---|
| | 310 | self.kwargs = kwargs |
|---|
| | 311 | |
|---|
| | 312 | def render(self, context): |
|---|
| | 313 | from django.core.urlresolvers import reverse, NoReverseMatch |
|---|
| | 314 | args = [arg.resolve(context) for arg in self.args] |
|---|
| | 315 | kwargs = dict([(k, v.resolve(context)) for k, v in self.kwargs.items()]) |
|---|
| | 316 | try: |
|---|
| | 317 | return reverse(self.view_name, args=args, kwargs=kwargs) |
|---|
| | 318 | except NoReverseMatch: |
|---|
| | 319 | try: |
|---|
| | 320 | project_name = settings.SETTINGS_MODULE.split('.')[0] |
|---|
| | 321 | return reverse(project_name + '.' + self.view_name, args=args, kwargs=kwargs) |
|---|
| | 322 | except NoReverseMatch: |
|---|
| | 323 | return '' |
|---|
| | 324 | |
|---|
| | 865 | def url(parser, token): |
|---|
| | 866 | """ |
|---|
| | 867 | Returns an absolute URL matching given view with its parameters. This is a mean to |
|---|
| | 868 | define links that aren't tied to a particular url configuration: |
|---|
| | 869 | |
|---|
| | 870 | {% url path.to.some_view arg1,arg2,name1=value1 %} |
|---|
| | 871 | |
|---|
| | 872 | The first argument is a path to a view. It can be an absolute python path or just |
|---|
| | 873 | ``app_name.view_name`` without the project name if the view is inside the project. |
|---|
| | 874 | Other arguments are comma-separated values that will be filled in place of |
|---|
| | 875 | positional and keyword arguments in the URL. All arguments for the URL should be |
|---|
| | 876 | present. |
|---|
| | 877 | |
|---|
| | 878 | For example if you have a view ``app_name.client`` taking client's id and the |
|---|
| | 879 | corresponding line in the urlconf looks like this: |
|---|
| | 880 | |
|---|
| | 881 | ('^client/(\d+)/$', 'app_name.client') |
|---|
| | 882 | |
|---|
| | 883 | ... and this app's urlconf is included into the project's urlconf under some path: |
|---|
| | 884 | |
|---|
| | 885 | ('^clients/', include('project_name.app_name.urls')) |
|---|
| | 886 | |
|---|
| | 887 | ... then in a template you can create a link for a certain client like this: |
|---|
| | 888 | |
|---|
| | 889 | {% url app_name.client client.id %} |
|---|
| | 890 | |
|---|
| | 891 | The URL will look like ``/clients/client/123/``. |
|---|
| | 892 | """ |
|---|
| | 893 | bits = token.contents.split(' ', 2) |
|---|
| | 894 | if len(bits) < 2: |
|---|
| | 895 | raise TemplateSyntaxError, "'url' takes at least one argument (path to a view)" |
|---|
| | 896 | args = [] |
|---|
| | 897 | kwargs = {} |
|---|
| | 898 | if len(bits) > 2: |
|---|
| | 899 | for arg in bits[2].split(','): |
|---|
| | 900 | if '=' in arg: |
|---|
| | 901 | k, v = arg.split('=', 1) |
|---|
| | 902 | kwargs[k] = parser.compile_filter(v) |
|---|
| | 903 | else: |
|---|
| | 904 | args.append(parser.compile_filter(arg)) |
|---|
| | 905 | return URLNode(bits[1], args, kwargs) |
|---|
| | 906 | url = register.tag(url) |
|---|
| | 907 | |
|---|