Chris McKinnel
Chris McKinnel

Reputation: 15082

Using defaults with app.add_url_rule in Flask

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?

Upvotes: 3

Views: 18424

Answers (2)

Devi
Devi

Reputation: 5443

A complete example of a similar thing is there in the flask docs - https://flask.palletsprojects.com/en/1.1.x/views/

Upvotes: 1

Chris McKinnel
Chris McKinnel

Reputation: 15082

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.

Upvotes: 4

Related Questions