Using defaults with app.add_url_rule in Flask

flask, python

Solution

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.

Problem

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?

Original source