Using defaults with app.add_url_rule in Flask


Question

I am setting a url endpoint with the following:

manager.py

from xxx import ContactAPI
from xxx.models import Contact

# self.app is my Flask app
# self.session is SQLAlchemy Session

api_name = 'contact'
instance_endpoint = '/%s/<int:instid>' % api_name
methods = ['GET']

api_view = ContactAPI.as_view(api_name, self.session,
                              Contact, app)

self.app.add_url_rule(instance_endpoint, methods=methods, 
                      defaults={'instid': None},
                      view_func=api_view)

And overriding get() in my ContactAPI class:

views.py

from flask.views import MethodView

class ContactAPI(MethodView):

    def __init__(self, session, model, app, *args, **kwargs):
        super(ContactAPI, self).__init__(*args, **kwargs)

    def get(self, instid):
        print instid

When I hit the URL /contact/1 I get instid printed as None.

When I remove the defaults={'instid': None}, line from manager.py, I get instid printed as 1.

Why is having the defaults line in my call to add_url_rule overriding what I'm putting in my URL?

1
3
3/14/2013 10:12:17 PM

Accepted Answer

It turns out I need to register two endpoints when using defaults.

Because {'instid': None} is passed into get() in my ContactAPI view as a kwarg, I need to tell Flask to set instid to None when the URL /contact is hit.

When I hit /contact/1, I need to use <int:instid>. To do this, I need to remove the defaults kwarg in my call to add_url_rule().

manager.py

from xxx import ContactAPI
from xxx.models import Contact

# self.app is my Flask app
# self.session is SQLAlchemy Session

api_name = 'contact'
instance_endpoint = '/%s/<int:instid>' % api_name
collection_endpoint = '/%s' % api_name

methods = ['GET']

api_view = ContactAPI.as_view(api_name, self.session,
                              Contact, app)

self.app.add_url_rule(instance_endpoint, methods=methods, 
                      view_func=api_view)

self.app.add_url_rule(collection_endpoint, methods=methods, 
                      defaults={'instid': None},
                      view_func=api_view)

Relevant Werkzeug docs: http://werkzeug.pocoo.org/docs/routing/#werkzeug.routing.Rule

Thanks to asdf in the #flask IRC channel for pointing this out.

3
3/14/2013 10:41:50 PM

A complete example of a similar thing is there in the flask docs - http://flask.pocoo.org/docs/0.10/views/#method-views-for-apis


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon