Flask รองรับนิพจน์ทั่วไปในการกำหนดเส้นทาง URL หรือไม่


101

ฉันเข้าใจว่า Flask มีตัวแปลง int, float และ path แต่แอปพลิเคชันที่เรากำลังพัฒนามีรูปแบบที่ซับซ้อนกว่าใน URL

มีวิธีที่เราสามารถใช้นิพจน์ทั่วไปเช่นเดียวกับใน Django ได้หรือไม่?

คำตอบ:


193

แม้ว่า Armin จะเอาชนะฉันด้วยคำตอบที่เป็นที่ยอมรับฉันคิดว่าฉันจะแสดงตัวอย่างสั้น ๆ ว่าฉันใช้ตัวจับคู่ regex ใน Flask ได้อย่างไรในกรณีที่ใครก็ตามต้องการตัวอย่างการทำงานว่าจะทำได้อย่างไร

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 นี้ควรส่งคืนด้วย 200: http: // localhost: 5000 / abc0-foo /

URL นี้ควรจะกลับมาพร้อมกับ 404: http: // localhost: 5000 / abcd-foo /


4
แต่นี่หมายความว่ามีการรวบรวมนิพจน์ทั่วไปหรือได้รับการประเมินทันที?
Games Brainiac

1
ดูเหมือนว่า regex จะได้รับการประเมินโดยตรงที่รันไทม์ สิ่งนี้ไม่ควรเป็นปัญหาสำหรับแอพขนาดเล็ก (หรือแอพที่ใช้ regex ซ้ำหลาย ๆ ครั้งฉันคิดว่า) เนื่องจากรูปแบบ regex สองตัวสุดท้ายถูกเก็บไว้ในหน่วยความจำ
bbenne10

6
วิธีนี้ทำงานอย่างไร? รูปแบบถูกตั้งค่าเป็นself.regexแต่การจับคู่เกิดขึ้นที่ไหน?
Justin

@ จัสตินการจับคู่เกิดขึ้นในภายในของ Werkzeug ที่นี่และที่ไหนสักแห่งในนิยามของกฎที่ฉันไม่พบ
AlexLordThorsen

49

คุณสามารถเชื่อมต่อในตัวแปลงแบบกำหนดเองที่ตรงกับนิพจน์ที่กำหนดเอง : Custom Converter

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})

ฉันไม่เข้าใจว่าto_pythonมันคืออะไร
corvid

17

คุณยังสามารถเขียนจับเส้นทางทุกประเภทและกำหนดเส้นทางที่ซับซ้อนภายในวิธีการ:

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()

สิ่งนี้จะตรงกับคำขอใด ๆ ดูรายละเอียดเพิ่มเติมได้ที่นี่: จับทั้งหมด URL


ฉันมีข้อผิดพลาดคุณจะแจ้งเบาะแสให้ฉันได้ไหม ไฟล์ "/app/catch_all.py" บรรทัด 234 ใน <module> @ app.route ('/ <path: path>', method = ['GET']) File "/ usr / local / lib / python2 7 / dist-package / flask / app.py "บรรทัด 1080 ในไฟล์มัณฑนากร" /usr/local/lib/python2.7/dist-packages/flask/app.py "บรรทัด 64 ในไฟล์ wrapper_func" / usr / local / lib / python2.7 / dist-package / flask / app.py "บรรทัด 1051 ในฟังก์ชันปลายทางที่มีอยู่ของ add_url_rule:% s '% endpoint) AssertionError: การแมปฟังก์ชั่นมุมมองจะเขียนทับฟังก์ชันปลายทางที่มีอยู่: test
จุดประกาย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.