views:

446

answers:

1

I have URLs like http://example.com/depict?smiles=CO&width=200&height=200 (and with several other optional arguments)

My urls.py contains:

urlpatterns = patterns('',
    (r'^$', 'cansmi.index'),
    (r'^cansmi$', 'cansmi.cansmi'),
    url(r'^depict$', cyclops.django.depict, name="cyclops-depict"),

I can go to that URL and get the 200x200 PNG that was constructed, so I know that part works.

In my template from the "cansmi.cansmi" response I want to construct a URL for the named template "cyclops-depict" given some query parameters. I thought I could do

{% url cyclops-depict smiles=input_smiles width=200 height=200 %}

where "input_smiles" is an input to the template via a form submission. In this case it's the string "CO" and I thought it would create a URL like the one at top.

This template fails with a TemplateSyntaxError:

Caught an exception while rendering: Reverse for 'cyclops-depict' with arguments '()' and keyword arguments '{'smiles': u'CO', 'height': 200, 'width': 200}' not found.

This is a rather common error message both here on StackOverflow and elsewhere. In every case I found, people were using them with parameters in the URL path regexp, which is not the case I have where the parameters go into the query.

That means I'm doing it wrong. How do I do it right? That is, I want to construct the full URL, including path and query parameters, using something in the template.

For reference,

% python manage.py shell
Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.core.urlresolvers import reverse
>>> reverse("cyclops-depict", kwargs=dict())
'/depict'
>>> reverse("cyclops-depict", kwargs=dict(smiles="CO"))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Library/Python/2.6/site-packages/django/core/urlresolvers.py", line 356, in reverse
    *args, **kwargs)))
  File "/Library/Python/2.6/site-packages/django/core/urlresolvers.py", line 302, in reverse
    "arguments '%s' not found." % (lookup_view_s, args, kwargs))
NoReverseMatch: Reverse for 'cyclops-depict' with arguments '()' and keyword arguments '{'smiles': 'CO'}' not found.
+4  A: 

Your regular expresion has no place holders (that's why you are getting NoReverseMatch):

url(r'^depict$', cyclops.django.depict, name="cyclops-depict"),

You could do it like this:

{% url cyclops-depict %}?smiles=CO&width=200&height=200

URLconf search does not include GET or POST parameters

Or if you wish to use {% url %} tag you should restructure your url pattern to something like

r'^depict/(?P<width>\d+)/(?P<height>\d+)/(?P<smiles>\w+)$' 

then you could do something like

{% url cyclops-depict 200 200 "CO" %}

Follow-up:

Simple example for custom tag:

from django.core.urlresolvers import reverse
from django import template
register = template.Library()

@register.tag(name="myurl")
def myurl(parser, token):
    tokens = token.split_contents()
    return MyUrlNode(tokens[1:])

class MyUrlNode(template.Node):
    def __init__(self, tokens):
        self.tokens = tokens
    def render(self, context):
        url = reverse('cyclops-depict')
        qs = '&'.join([t for t in self.tokens])
        return '?'.join((url,qs))

You could use this tag in your templates like so:

{% myurl width=200 height=200 name=SomeName %}

and hopefully it should output something like

/depict?width=200&height=200&name=SomeName
rebus
Andrew Dalke
If you want to encapsulate the logic for building URLs you could just write your own [custom templatetag][1]. Make it take parameters such as `entry` or even a complete context and return built URL. This way you could even emulate `url` tag and have the syntax you like.. [1]: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#custom-template-tags-and-filters
rebus
I'm getting back to this project. One thing is I'm teaching this to non-software developers (they are computational chemists who do some programming) and I don't want to explain all this. I'll have to think about this some more. Thanks for the followup!
Andrew Dalke