1

Приветствую.

Во Flask привязка к приложению контроллеров, обработчиков событий и т. п. принято делать непосредственно в модулях, но вот захотелось вынести эти действия во внешний файл или в питоновский словарь. Например, вот так бы это выглядело (Yaml):

# это секция для настройки контроллеров
view: [
  {
    # это мы указываем вызываемый объект (например функцию index)
    action: application.view.index,
    # а тут шаблоны url`ов при совпадении с которыми вызывается функция index
    route: [/, /index]
  }
],

Аналогичное привычным способом выглядело бы так:

# application.view.index

from app import app

@app.route('/')
@app.route('/index')
def index():
    return 'Hello, World'

Преимущество в том, что теперь мы можем, не залезая во внутрь исходников, подменять обработчики, контроллеры и т. д. Но... вопрос в том, как такой подход соотносится с философией самого Flask, и вообще здоровая ли это идея, были ли еще у кого-нибудь при работе с этим фреймворком такие потребности?

Спасибо за внимание!

2 ответа 2

0

В общем-то я скажу тебе так, если данный метод не просто приемлем для тебя, а необходим, то простого описания в документации к проекту будет достаточно, чтобы избежать каких-либо непоняток.

2
  • Ну счет необходимости пока не могу сказать, но что так будет значительно удобнее, могу сказать наверняка, главное чтобы это не усложнило понимание взаимодействия модулей в будущем
    – triplustri
    25 фев 2015 в 12:44
  • Все эти философии чаще всего являются просто рекомендациями и если где-то нет четких, прописанных как pep, правил, требующих неукоснительного соблюдения, то ими в принципе можно пренебречь. Достаточно просто описать в доке, что "так-то так-то, данная структура на мой взгляд кажется более здоровой и правильной в данном проекте" и никто вам ничего не скажет скорее всего. Если коротко, то да, вы вольны делать все что захотите, вы разработчик! И только вы знаете как лучше будет для результирующего продукта.
    – deterok
    25 фев 2015 в 13:02
0

В документации здесь и здесь об этом расскаызвается.

Есть методы, которые могут в этом помочь:

 add_url_rule(rule, endpoint=None, view_func=None, **options)

который работает как стандартный декоратор:

@app.route('/')
def index():
    pass

что эквивалентно

def index():
    pass
app.add_url_rule('/', 'index', index)

Если view_func не указана, то так:

app.view_functions['index'] = index

С request.method, соответственно так:

def index():
    if request.method == 'OPTIONS':
        # custom options handling here
        ...
    return 'Hello World!'
index.provide_automatic_options = False
index.methods = ['GET', 'OPTIONS']

app.add_url_rule('/', index)

Если я Вас правильно понял, то это то, что Вам нужно. При генерации словаря, можно автоматически импортировать эксншы.

Вот так я автоматически импортирую Blueprints:

def create_app():
    ...
    register_routes(app)
    ...
    return app


def register_routes(app):
    """Register routes."""
    from . import controllers
    from flask.blueprints import Blueprint

    for module in _import_submodules_from_package(controllers):
        bp = getattr(module, 'bp')
        if bp and isinstance(bp, Blueprint):
            app.register_blueprint(bp)



def _import_submodules_from_package(package):
    import pkgutil

    modules = []
    for importer, modname, ispkg in pkgutil.iter_modules(package.__path__,
                                                         prefix=package.__name__ + "."):
        modules.append(__import__(modname, fromlist="dummy"))
    return modules

А уже в самих Blueprints можно реализовывать те самые экшны.

Так же, возможно, пригодится такой хелпер:

rules = {}
for endpoint, _rules in iteritems(app.url_map._rules_by_endpoint):
    if any(item in endpoint for item in ['_debug_toolbar', 'debugtoolbar', 'static', 'admin']):
        continue
    rules[endpoint] = [{'rule': rule.rule} for rule in _rules]

Который позволяет легко получить урлы для последующего маппинга, с обходом debugtoolbar, admin и пр. , к примеру, для последующей генерации sitemap.

Или вот такая команда, для manage.py, чтобы всегда можно было оперативно просмотреть, какие урлы сейчас зарегистрированы:

@manager.command
def list_routes():
    import urllib.request
    from flask import url_for
    output = []
    for rule in app.url_map.iter_rules():
        options = {}
        for arg in rule.arguments:
            options[arg] = "[{0}]".format(arg)

        methods = ','.join(rule.methods)
        url = url_for(rule.endpoint, **options)
        line = urllib.request.unquote("{:50s} {:20s} {}".format(rule.endpoint, methods, url))


    for line in sorted(output):
        print (line)  

Ваш ответ

By clicking “Отправить ответ”, you agree to our terms of service and acknowledge you have read our privacy policy.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками или задайте свой вопрос.