Apakah Flask mendukung ekspresi reguler dalam perutean URL-nya?

100

Saya mengerti bahwa Flask memiliki konverter int, float dan path, tetapi aplikasi yang kami kembangkan memiliki pola yang lebih kompleks dalam URL-nya.

Adakah cara kita bisa menggunakan ekspresi reguler, seperti di Django?

Alistair
sumber

Jawaban:

192

Meskipun Armin mengalahkan saya dengan jawaban yang diterima, saya pikir saya akan menunjukkan contoh singkat tentang bagaimana saya menerapkan pencocok regex di Flask kalau-kalau ada yang menginginkan contoh yang berfungsi tentang bagaimana ini dapat dilakukan.

from flask import Flask
from werkzeug.routing import BaseConverter

app = Flask(__name__)

class RegexConverter(BaseConverter):
    def __init__(self, url_map, *items):
        super(RegexConverter, self).__init__(url_map)
        self.regex = items[0]


app.url_map.converters['regex'] = RegexConverter

@app.route('/<regex("[abcABC0-9]{4,6}"):uid>-<slug>/')
def example(uid, slug):
    return "uid: %s, slug: %s" % (uid, slug)


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

URL ini harus dikembalikan dengan 200: http: // localhost: 5000 / abc0-foo /

URL ini akan kembali dengan 404: http: // localhost: 5000 / abcd-foo /

Philip Southam
sumber
4
Tetapi apakah ini berarti bahwa ekspresi reguler dikompilasi, atau dievaluasi dengan cepat?
Game Brainiac
1
Sepertinya regex akan dievaluasi langsung pada waktu proses. Ini seharusnya tidak menjadi masalah untuk aplikasi yang lebih kecil (atau aplikasi yang menggunakan regex berkali-kali, menurut saya) karena beberapa pola regex terakhir disimpan dan dikompilasi dalam memori.
bbenne10
5
Bagaimana cara kerjanya? Polanya disetel ke self.regex, tetapi di mana pertandingan terjadi?
Justin
@Justin Pencocokan terjadi di internal Werkzeug Di sini dan di suatu tempat dalam definisi aturan yang belum saya temukan.
AlexLordThorsen
49

Anda dapat mengaitkan konverter kustom yang cocok dengan ekspresi arbitrer: Konverter Kustom

from random import randrange
from werkzeug.routing import Rule, Map, BaseConverter, ValidationError

class BooleanConverter(BaseConverter):

    def __init__(self, url_map, randomify=False):
        super(BooleanConverter, self).__init__(url_map)
        self.randomify = randomify
        self.regex = '(?:yes|no|maybe)'

    def to_python(self, value):
        if value == 'maybe':
            if self.randomify:
                return not randrange(2)
            raise ValidationError()
        return value == 'yes'

    def to_url(self, value):
        return value and 'yes' or 'no'

url_map = Map([
    Rule('/vote/<bool:werkzeug_rocks>', endpoint='vote'),
    Rule('/vote/<bool(randomify=True):foo>', endpoint='foo')
], converters={'bool': BooleanConverter})
Armin Ronacher
sumber
Saya tidak mengerti apa yang to_pythondilakukannya
corvid
17

Anda juga dapat menulis semua jenis rute dan melakukan perutean kompleks dalam metode:

from flask import Flask
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'], defaults={'path': ''})
@app.route('/<path:path>', methods=['GET', 'POST'])
def catch_all(path):
    return 'You want path: %s' % path

if __name__ == '__main__':
    app.run()

Ini akan cocok dengan permintaan apa pun. Lihat detail lebih lanjut di sini: URL Catch-All .

Zorayr
sumber
Saya mengalami kesalahan, maukah Anda memberi saya beberapa petunjuk? File "/app/catch_all.py", baris 234, di <module> @ app.route ('/ <path: path>', methods = ['GET']) File "/ usr / local / lib / python2. 7 / dist-packages / flask / app.py ", baris 1080, di File dekorator" /usr/local/lib/python2.7/dist-packages/flask/app.py ", baris 64, dalam file wrapper_func" / usr / local / lib / python2.7 / dist-packages / flask / app.py ", baris 1051, di add_url_rule 'existing endpoint function:% s'% endpoint) AssertionError: View function mapping menimpa fungsi endpoint yang ada: test
percikan