mirror of
				https://github.com/django/django.git
				synced 2025-11-04 05:35:37 +00:00 
			
		
		
		
	Fixed #2606 -- Added tag for working out the URL of a particular view function.
All work done by Ivan Sagalaev. git-svn-id: http://code.djangoproject.com/svn/django/trunk@4494 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		
							parent
							
								
									58ae80b5ea
								
							
						
					
					
						commit
						0fabbf8ce8
					
				
					 6 changed files with 131 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -315,6 +315,25 @@ class TemplateTagNode(Node):
 | 
			
		|||
    def render(self, context):
 | 
			
		||||
        return self.mapping.get(self.tagtype, '')
 | 
			
		||||
 | 
			
		||||
class URLNode(Node):
 | 
			
		||||
    def __init__(self, view_name, args, kwargs):
 | 
			
		||||
        self.view_name = view_name
 | 
			
		||||
        self.args = args
 | 
			
		||||
        self.kwargs = kwargs
 | 
			
		||||
      
 | 
			
		||||
    def render(self, context):
 | 
			
		||||
        from django.core.urlresolvers import reverse, NoReverseMatch
 | 
			
		||||
        args = [arg.resolve(context) for arg in self.args]
 | 
			
		||||
        kwargs = dict([(k, v.resolve(context)) for k, v in self.kwargs.items()])
 | 
			
		||||
        try:
 | 
			
		||||
            return reverse(self.view_name, args=args, kwargs=kwargs)
 | 
			
		||||
        except NoReverseMatch:
 | 
			
		||||
            try:
 | 
			
		||||
                project_name = settings.SETTINGS_MODULE.split('.')[0]
 | 
			
		||||
                return reverse(project_name + '.' + self.view_name, args=args, kwargs=kwargs)
 | 
			
		||||
            except NoReverseMatch:
 | 
			
		||||
                return ''
 | 
			
		||||
 | 
			
		||||
class WidthRatioNode(Node):
 | 
			
		||||
    def __init__(self, val_expr, max_expr, max_width):
 | 
			
		||||
        self.val_expr = val_expr
 | 
			
		||||
| 
						 | 
				
			
			@ -868,6 +887,50 @@ def templatetag(parser, token):
 | 
			
		|||
    return TemplateTagNode(tag)
 | 
			
		||||
templatetag = register.tag(templatetag)
 | 
			
		||||
 | 
			
		||||
def url(parser, token):
 | 
			
		||||
    """
 | 
			
		||||
    Returns an absolute URL matching given view with its parameters. This is a
 | 
			
		||||
    way to define links that aren't tied to a particular url configuration:
 | 
			
		||||
    
 | 
			
		||||
        {% url path.to.some_view arg1,arg2,name1=value1 %}
 | 
			
		||||
    
 | 
			
		||||
    The first argument is a path to a view. It can be an absolute python path
 | 
			
		||||
    or just ``app_name.view_name`` without the project name if the view is
 | 
			
		||||
    located inside the project.  Other arguments are comma-separated values
 | 
			
		||||
    that will be filled in place of positional and keyword arguments in the
 | 
			
		||||
    URL. All arguments for the URL should be present.
 | 
			
		||||
 | 
			
		||||
    For example if you have a view ``app_name.client`` taking client's id and
 | 
			
		||||
    the corresponding line in a urlconf looks like this:
 | 
			
		||||
    
 | 
			
		||||
        ('^client/(\d+)/$', 'app_name.client')
 | 
			
		||||
    
 | 
			
		||||
    and this app's urlconf is included into the project's urlconf under some
 | 
			
		||||
    path:
 | 
			
		||||
    
 | 
			
		||||
        ('^clients/', include('project_name.app_name.urls'))
 | 
			
		||||
    
 | 
			
		||||
    then in a template you can create a link for a certain client like this:
 | 
			
		||||
    
 | 
			
		||||
        {% url app_name.client client.id %}
 | 
			
		||||
    
 | 
			
		||||
    The URL will look like ``/clients/client/123/``.
 | 
			
		||||
    """
 | 
			
		||||
    bits = token.contents.split(' ', 2)
 | 
			
		||||
    if len(bits) < 2:
 | 
			
		||||
        raise TemplateSyntaxError, "'%s' takes at least one argument (path to a view)" % bits[0]
 | 
			
		||||
    args = []
 | 
			
		||||
    kwargs = {}
 | 
			
		||||
    if len(bits) > 2:
 | 
			
		||||
        for arg in bits[2].split(','):
 | 
			
		||||
            if '=' in arg:
 | 
			
		||||
                k, v = arg.split('=', 1)
 | 
			
		||||
                kwargs[k] = parser.compile_filter(v)
 | 
			
		||||
            else:
 | 
			
		||||
                args.append(parser.compile_filter(arg))
 | 
			
		||||
    return URLNode(bits[1], args, kwargs)
 | 
			
		||||
url = register.tag(url)
 | 
			
		||||
 | 
			
		||||
#@register.tag
 | 
			
		||||
def widthratio(parser, token):
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -829,6 +829,40 @@ The argument tells which template bit to output:
 | 
			
		|||
 | 
			
		||||
Note: ``opencomment`` and ``closecomment`` are new in the Django development version.
 | 
			
		||||
 | 
			
		||||
url
 | 
			
		||||
~~~
 | 
			
		||||
 | 
			
		||||
Returns an absolute URL matching a given view function. This is a way to
 | 
			
		||||
define links that aren't tied to a particular url configuration.
 | 
			
		||||
 | 
			
		||||
::
 | 
			
		||||
 | 
			
		||||
    {% url path.to.some_view arg1,arg2,name1=value1 %}
 | 
			
		||||
 | 
			
		||||
The first argument is a path to a view function. It can be an absolute python
 | 
			
		||||
path or just ``app_name.view_name`` without the project name if the view is
 | 
			
		||||
located inside the project.  Other arguments are comma-separated values that
 | 
			
		||||
will be use as positional and keyword arguments in the URL. All arguments
 | 
			
		||||
needed by the URL resolver should be present.
 | 
			
		||||
 | 
			
		||||
For example, suppose you have a view ``app_name.client`` taking client's id
 | 
			
		||||
and the corresponding line in a urlconf looks like this::
 | 
			
		||||
 | 
			
		||||
    ('^client/(\d+)/$', 'app_name.client')
 | 
			
		||||
 | 
			
		||||
If this app's urlconf is included into the project's urlconf under a path
 | 
			
		||||
such as
 | 
			
		||||
 | 
			
		||||
::
 | 
			
		||||
 | 
			
		||||
    ('^clients/', include('project_name.app_name.urls'))
 | 
			
		||||
 | 
			
		||||
then, in a template, you can create a link to this view like this::
 | 
			
		||||
 | 
			
		||||
    {% url app_name.client client.id %}
 | 
			
		||||
 | 
			
		||||
The URL rendered in the template will then look like ``/clients/client/123/``.
 | 
			
		||||
 | 
			
		||||
widthratio
 | 
			
		||||
~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -645,6 +645,17 @@ class Templates(unittest.TestCase):
 | 
			
		|||
            # Compare to a given parameter
 | 
			
		||||
            'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=1), 'b':NOW - timedelta(days=2)}, '1 day'),
 | 
			
		||||
            'timeuntil05' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=2), 'b':NOW - timedelta(days=2, minutes=1)}, '1 minute'),
 | 
			
		||||
 | 
			
		||||
            ### URL TAG ########################################################
 | 
			
		||||
            # Successes
 | 
			
		||||
            'url01' : ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
 | 
			
		||||
            'url02' : ('{% url regressiontests.templates.views.client_action client.id,action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
 | 
			
		||||
            'url03' : ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),
 | 
			
		||||
 | 
			
		||||
            # Failures
 | 
			
		||||
            'url04' : ('{% url %}', {}, template.TemplateSyntaxError),
 | 
			
		||||
            'url05' : ('{% url no_such_view %}', {}, ''),
 | 
			
		||||
            'url06' : ('{% url regressiontests.templates.views.client no_such_param="value" %}', {}, ''),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # Register our custom template loader.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								tests/regressiontests/templates/urls.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/regressiontests/templates/urls.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
from django.conf.urls.defaults import *
 | 
			
		||||
from regressiontests.templates import views
 | 
			
		||||
 | 
			
		||||
urlpatterns = patterns('',
 | 
			
		||||
 | 
			
		||||
    # Test urls for testing reverse lookups
 | 
			
		||||
    (r'^$', views.index),
 | 
			
		||||
    (r'^client/(\d+)/$', views.client),
 | 
			
		||||
    (r'^client/(\d+)/(?P<action>[^/]+)/$', views.client_action),
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										10
									
								
								tests/regressiontests/templates/views.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/regressiontests/templates/views.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
# Fake views for testing url reverse lookup
 | 
			
		||||
 | 
			
		||||
def index(request):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
def client(request, id):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
def client_action(request, id, action):
 | 
			
		||||
    pass
 | 
			
		||||
| 
						 | 
				
			
			@ -7,4 +7,7 @@ urlpatterns = patterns('',
 | 
			
		|||
    # Always provide the auth system login and logout views
 | 
			
		||||
    (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
 | 
			
		||||
    (r'^accounts/logout/$', 'django.contrib.auth.views.login'),
 | 
			
		||||
 | 
			
		||||
    # test urlconf for {% url %} template tag
 | 
			
		||||
    (r'^url_tag/', include('regressiontests.templates.urls')),
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue