10

Given that Flask Routes are not pattern matched from top to bottom, how does one deal with the following problem?

I have the following routes:

  1. /<poll_key>/close
  2. /<poll_key>/<participant_key>

If I make a request to http://localhost:5000/example-poll-key/close, Flask matches it as pattern 2, assigning the string 'close' to the <participant_key> URL parameter. How can I make the <poll_key>/close route get matched before the <participant_key> route?

dmoench
  • 704
  • 4
  • 11
  • 24

1 Answers1

6

See my other answer to the same question: https://stackoverflow.com/a/17146563/880326.

Looks like the best solution is to add your own converters and create routes as

/<poll_key>/close
/<poll_key>/<no(close):participant_key>

where the no converter is defined

class NoConverter(BaseConverter):

    def __init__(self, map, *items):
        BaseConverter.__init__(self, map)
        self.items = items

    def to_python(self, value):
        if value in self.items:
            raise ValidationError()
        return value

Update:

I missed match_compare_key:

  1. for static endpoint: (True, -2, [(0, -6), (1, 200)])
  2. for /<poll_key>/close: (True, -2, [(1, 100), (0, -5)])
  3. for /<poll_key>/<participant_key>: (True, -2, [(1, 100), (1, 100)])

This means that static has higher priority than the others and close has higher priority than <participant_key>.

Example:

from flask import Flask

app = Flask(__name__)
app.add_url_rule('/<poll_key>/close', 'close',
                 lambda **kwargs: 'close\t' + str(kwargs))
app.add_url_rule('/<poll_key>/<participant_key>', 'p_key',
                 lambda **kwargs: 'p_key\t' + str(kwargs))


client = app.test_client()

print client.get('/example-poll-key/close').data
print client.get('/example-poll-key/example-participant-key').data

This outputs:

close   {'poll_key': u'example-poll-key'}
p_key   {'participant_key': u'example-participant-key', 'poll_key': u'example-poll-key'}

Looks like this is the right behaviour.

Community
  • 1
  • 1
tbicr
  • 24,790
  • 12
  • 81
  • 106
  • Thanks for the helpful tip. I didn't know about Converters. This was a great solution for simplified example I asked about, however I have a lot more keywords than 'close' that I did not want to match the `participant_key` url component. So effectively saying "match if not in the set (close, admin, add, etc)" would get pretty long. I ended up using this [RegexConverter solution](http://stackoverflow.com/questions/5870188/does-flask-support-regular-expressions-in-its-url-routing) and making sure my `participant_key` url component had a certain prefix. – dmoench Jul 26 '13 at 19:52
  • I was a little wrong, see my update. Can you get rules `arguments` and `_weights` values for this two rules? – tbicr Jul 28 '13 at 07:42