Flask中的动态render_template()

0 投票
2 回答
6593 浏览
提问于 2025-04-18 12:44

我在我的Flask应用中有几个视图,每个视图都有自己的子视图,而且每个子视图都有一些小模板。它们的视觉展示和网址结构大概是这样的:

|-settings ___________ [@app.route(/manage)]
|--menu_settings _____ [@app.route(/manage?current=menu_settings)]
|--main_settings _____ [@app.route(/manage?current=main_settings)]
|--additional_settings [@app.route(/manage?current=additional_settings)]

|-online_store [@app.route(/online_store)]
|--delivery __ [@app.route(/online_store?current=delivery)]
|--payment ___ [@app.route(/online_store?current=payment)]
|--store _____ [@app.route(/online_store?current=store)]

我想做的是使用if或者switch条件。比如说:

@admin.route('/manage', methods = ['GET', 'POST'])  
@login_required
def manage(current = ''):

    current = request.args.get('current') 

    if current == 'menu_settings':
        return render_template('admin/manage/site_figuration.html',
            title = 'Site figuration',
            current = current)
    elif current == 'internet_market':
        return render_template('admin/manage/internet_market.html',
        title = 'Internet market',
        current = current)
    else:
        return '404 - Template not found'

我想问的是,我这样做对吗?有没有其他更简单的方法来解决这个问题?使用这种方法合理吗?还是我必须使用JQuery的load()方法?

2 个回答

2

不,我觉得你这样做不太对。

为什么不直接创建多个视图呢?

@admin.route('/manage/menu', methods = ['GET', 'POST'])  
@login_required
def manage_menu():
  return render_template('admin/manage/site_figuration.html',
            title = 'Site figuration',
            current = request.args.get('current') )

@admin.route('/manage/internet_market', methods = ['GET', 'POST'])  
@login_required
def manage_market():
  return render_template('admin/manage/internet_market.html',
        title = 'Internet market',
        current = request.args.get('current') )

这种方法更容易扩展和维护。

如果你真的想的话,可以把这些内容封装成一个装饰器或者基于类的视图(如果Flask支持的话)。

编辑

我主要是在Pyramid框架下工作,而不是Flask(说实话,你可能想考虑换到Pyramid,因为它和Flask类似,但功能更强大)。

在Pyramid中,我会使用一个基于类的视图,可能看起来像这样。

@view_defaults(permission='admin')
class admin_views:
  def __init__(self, request):
    self.request = request
    # Assign anything else you want to precalculate
    # for all views to a self variable

  @view("manage_menu", renderer='manage_menu.jinja2')
  def menu(self):
    return {'title':'Manage Menu'} #These are your template variables

  @view("internet_market", renderer='internet_market.jinja2')
  def market(self):
    return {'title': 'Internet Market"}

然后你的路由设置会像这样:

config.add_route('manage_menu', '/manage/menu')
config.add_route('internet_market', '/manage/market')

真正强大的地方在于你开始使用参数的时候。

# Now the request.params dict will have a key of 'product'
# with whatever that path segment is.
config.add_route('product_view','/products/{product}')

你还可以很容易地生成链接,比如:

route_path('view_name', request_obj, #any variables here)

例如:

# That'll generate a proper link.
# If the client is using SSL it'll be an https link, etc.
route_path('product_view', self.request, product=5).
3

看起来你把事情搞得太复杂了。这样做怎么样:

@admin.route('/manage')
@admin.route('/manage/<current>')
@login_required
def manage(current = None):
    if current == 'menu_settings':
        template = 'admin/manage/site_configuration.html'
        title = 'Site configuration'
    elif current == 'internet_market':
        template = 'admin/manage/internet_market.html'
        title = 'Internet market'
    elif current is None:
        template = 'admin/manage/default.html'
        title = 'Default page for manage'
    else:
        flask.abort(404)

    return render_template(template, title=title, current=current)

不过我觉得有多个路径会是更正确的做法。为什么要重新发明轮子呢?

@admin.route('/manage')
@login_required
def manage():
    return render_template('admin/manage/default.html',
                           title='Default page for manage',
                           current=None)

@admin.route('/manage/menu_settings')
@login_required
def manage_menu_settings():
    return render_template('admin/manage/site_configuration.html',
                           title='Site configuration',
                           current='menu_settings')

@admin.route('/manage/internet_market')
@login_required
def manage_internet_market():
    return render_template('admin/manage/internet_market.html',
                           title='Internet market',
                           current='internet_market')

注意:请记住,这段代码没有经过测试,可能会有错误或者拼写错误。

撰写回答