18

Have found one or two people on the interwebs with similar problems, but haven't seen a solution posted anywhere. I'm getting a build error from the code/template below, but can't figure out where the issue is or why it's occurring. It appears that the template isn't recognizing the function, but don't know why this would be occurring. Any help would be greatly appreciated - have been pounding my against the keyboard for two nights now.

Function:

@app.route('/viewproj/<proj>', methods=['GET','POST'])
def viewproj(proj):

...

Template Excerpt:

{% for project in projects %}
  <li>
<a href="{{ url_for('viewproj', proj=project.project_name) }}">
{{project.project_name}}</a></li>
{% else %}
No projects
{% endfor %}

Error log: https://gist.github.com/1684250

EDIT: Also wanted to include that it's not recognizing the variable "proj" when building the URL, so it's just appending the value as a parameter. Here's an example: //myproject/viewproj?projname=what+up

Last few lines:

[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]   File "/srv/www/myproject.com/myproject/templates/layout.html", line 103, in top-level template code, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]     {% block body %}{% endblock %}, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]   File "/srv/www/myproject.com/myproject/templates/main.html", line 34, in block "body", referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]     <a href="{{ url_for('viewproj', proj=project.project_name) }}">, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]   File "/usr/lib/python2.7/dist-packages/flask/helpers.py", line 195, in url_for, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]     return ctx.url_adapter.build(endpoint, values, force_external=external), referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]   File "/usr/lib/pymodules/python2.7/werkzeug/routing.py", line 1409, in build, referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128]     raise BuildError(endpoint, values, method), referer: xx://myproject.com/
[Wed Jan 25 09:47:34 2012] [error] [client 199.58.143.128] BuildError: ('viewproj', {'proj': '12th'}, None), referer: xx://myproject.com/
4
  • Are you, by any chance, using blueprints? Are there any other routes defined for the viewproj function? Commented Jan 26, 2012 at 19:04
  • Nope. I'm still pretty early on - there's only 4 views each with their own route Commented Jan 26, 2012 at 19:33
  • Try removing stuff from your project, bit by bit, until you reduce the problem to a minimal test case. Commented Jan 27, 2012 at 12:31
  • Did you define viewproj more than once? Duplicate function names which are both routed are likely to cause this kind of issues. Commented Jun 1, 2012 at 17:10

7 Answers 7

26

url_for looks for a function, you pass it the name of the function you are wanting to call. So you should use :

{{ url_for('viewproj', proj=xxx) }}

I got the same problem. And I solved it accoring:Flask error: werkzeug.routing.BuildError

Sign up to request clarification or add additional context in comments.

1 Comment

I believe this is the correct answer because I got the same problem too.
22

Just solved the same problem, the solution is really funny.

Just add a '.' in front of your method name in url_for.

Like this:

<a href="{{ url_for('.viewproj', proj=project.project_name) }}">

And it should work now.

The document for this solution from Flask is http://flask.pocoo.org/docs/0.10/api/, and I quote:

flask.url_for(endpoint, **values) Generates a URL to the given endpoint with the method provided.

Variable arguments that are unknown to the target endpoint are appended to the generated URL as query arguments. If the value of a query argument is None, the whole pair is skipped. In case blueprints are active you can shortcut references to the same blueprint by prefixing the local endpoint with a dot (.).

This will reference the index function local to the current blueprint:

url_for('.index')

4 Comments

That's what I needed. Kind of non-intuitive. I guess whenever you start to have strings refer to actual variable names like a function name, things get weird.
This is indeed it for me! Was getting a similar werkzeug.routing.BuildError on the way url_for() is being called. With a dot(.) it solves the issue AND rendered the correct relative url! Thank you @Arthur Wang
Semi related. I was having BuildError issues for my production copy but not my local copy - I couldn't figure out why. I use Flask-Classy and the issue was that I needed to make sure the new view was registered to the app in the main app.py. For people with similar issues who come here via google.
It's also important, that the module with the route function is imported. I had the same BuildError just because I forgot to import view module.
1

I still reply to this even though it kind of has been answered already. The reason is for clarity. Even after reading them, I couldn't understand what was going on without looking at the source file for url_for().

A clean example:

<a href="{{ url_for('viewproj', proj='<projname>') }}">Project name</a>

@app.route('/viewproj/<projname>', methods=['GET','POST'])
def viewproj(proj):

Comments

0

See if 'project.project_name' is resolving correctly in the template. Are you passing 'projects' correctly to template? Hard code some value for 'proj' instead and see the url is getting generated. Something like:-

<a href="{{ url_for('viewproj', proj='new_project') }}">new project</a>

2 Comments

Thanks for the help. When I pass 'new_project' as a string it builds as //myproject/viewproj?projname=new_project. Would that imply the issue is on the view/routing side?
Your url_for() argument name in template is not matching with your view function. You are using 'projname' in your template, not 'proj' as you defined in you view. i.e instead of {{ url_for('viewproj', projname='new_project') }} use {{ url_for('viewproj', proj='new_project') }}.
0

You most likely have more than one routed function with the name viewproj.

Besides that, the output you posted does not correspond with the template code you posted. myproject/viewproj?projname=what+up means that projname=... was passed to url_for(), but your view function expects proj=...

Comments

-3

Seeing as you specify which methods are available on that endpoint I think you will have to pass which method you want into url_for.

url_for('viewproj', proj=project.project_name, method='GET')

4 Comments

I had actually pulled out the specification and was getting the same error. I'm looking into specifying it solely as "GET" to see if that makes a difference, but doesn't seem to be helping .
This is also causing it to append method='GET' to the url: //myproject.com/viewproj?projname=what+up&method=GET
Unrelated. The methods are specified in the route call because by default only GET is allowed. When building an URL you do not need to specify the method.
How would a GET URL look different from a POST URL?
-4

I googled for the same problem and found this, so I thought I would post what worked for me after I banged at it for a bit (In case anyone else landed here). Looks like it may just be a string concatenation issue

I had incorrectly "translated" my working code:

{% for project in projects %}
    <li>
    <a href="{{ url_for('viewproj', proj='%s') }}"|format(project.project_name)>
    {{project.project_name}}</a>
    </li>
{% else %}
    No projects
{% endfor %}

Interesting effect of the code above is some "padding?" added to the link url

But as I thought more about it, I was questioning whether the url_for adds any value in the template? The following line will accomplish the same thing for your anchor tag:

<a href="viewproj/{{ project.project_name }}">{{ project.project_name }}</a> 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.