Flask中的动态导航 [英] Dynamic navigation in Flask

查看:365
本文介绍了Flask中的动态导航的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的网站在Flask工作,所有这些都是由一个sqlite数据库提供的。每个页面在页面表中存储为一行,其中包含路径,标题,内容等内容。



结构是层次结构,页面可以有父级。因此,例如,约可能是一个页面,也可能是关于/某事和关于/蛋糕。所以我想创建一个导航栏,链接到所有具有/(/是根页面)父项的链接。另外,我还希望它也显示页面是开放的,并且该页面的所有父母。

例如,如果我们在about / cakes /松饼,除了总是显示的链接之外,我们还可以看到about / cakes的链接,像这样:

   - 关于/ 
- 蛋糕/
- 松饼
- Genoise
- 馅饼/
- 东西/
- 联络
- Legal
- 等等[/]

孩子,没有那些没有。

代码:

  @ app.route('/')
def index():
page = query_db('select * from page where path =/',one = True)
return render_template('page.html',page = page,bread = [''])

@ app.route('/< path>)
def page(path = None ):
page = query_db('select * from page where path =%s'%path,one = True)
bread = Bread(path)
返回render_template('page.html',page = page,crumbs = bread.links)

觉得我在这里有两个功能,就是违反DRY。但做导航将进一步侵犯它,因为我也希望在错误页面的东西导航。

但我似乎无法找到一个特别Flasky的方式来做到这一点。任何想法?

解决方案

flasky和pythonic方式将使用基于类的视图和模板层次结构



首先阅读这两个文档,然后你可以基于这种方法重构你的代码:

  class MainPage(MethodView):
navigation = False
context = {}
$ b $ def prepare(self,* args,** kwargs):
如果self.navigation:
self.context ['navigation'] = {
#building navigation
#基于request.args.get('page')
}
else:
self.context ['navigation'] = None
$ b $ def dispatch_request(self,* args,** kwargs):
self.context = dict()#应该请求无效的上下文,因为Views类的对象之间共享请求
self.prepare(self,* args,** kwargs)
返回超级(MainPage,self).dispatch_request(* ARGS,* * kwargs)
$ b $ class PageWithNavigation(MainPage):
navigation = True
$ b $ class ContentPage(PageWithNavigation):
def get(self):
page = {}#在这里你可以获得页面数据
self.context ['page'] = page
#self.context ['bread'] = bread
# self.context ['something_Else'] = something_Else
return render_template('page.html',** self.context)

然后您可以执行以下操作:
为main_page.html和page_with_navigation.html
创建单独的页面然后,您的每一页error.html,page.html,somethingelse.html 基于其中之一。
关键是动态地执行此操作:

将修改prepare方法一下:

<$ p $如果self.navigation:
self.context ['navigation'] = {
#building#
#in你的案例基于request.args.get('page')
}
else:
self.context ['navigation'] = None
#added another if to point on但如果self.navigation:
self.context ['extends_with'] =templates / page_with_navigation.html
else:
self,则可以与之前的
结合使用。 context ['extends_with'] =templates / main_page.html

和你的模板:
main_page.html

 <!DOCTYPE html> 
< html>
< head>
< title>< / title>
< / head>
< body>
{%block navigation%}
{%endblock%}
{%block main_content%}
{%endblock%}
< / body>
< / html>

page_with_navigation.html

  {%extends/templates/main_page.html%} 

{%block navigation%}
在这里您可以建立您的导航在导航上下文变量,已经在这里传递
{%endblock%}

page.html或任何其他some_page.html。保持简单!

注意第一行。您的视图设置了哪些页面应该放在那里,您可以通过设置navigation = view-class来轻松调整它。

  { %extends extends_with%} 

{%block main_content%}
这就是您的游戏页面。
哟不担心在这里导航,所有这些东西都必须设置在视图类和模板不应该担心他们
但是,如果你需要他们,他们仍然可用导航上下文变量
{ %endblock%}


I have a pretty simple site working in Flask that's all powered from an sqlite db. Each page is stored as a row in the page table, which holds stuff like the path, title, content.

The structure is hierarchical where a page can have a parent. So while for example, 'about' may be a page, there could also be 'about/something' and 'about/cakes'. So I want to create a navigation bar with links to all links that have a parent of '/' (/ is the root page). In addition, I'd like it to also show the page that is open and all parents of that page.

So for example if we were at 'about/cakes/muffins', in addition to the links that always show, we'd also see the link to 'about/cakes', in some manner like so:

- About/
  - Cakes/
    - Muffins
    - Genoise
  - Pies/
- Stuff/
- Contact
- Legal
- Etc.[/]

with trailing slashes for those pages with children, and without for those that don't.

Code:

@app.route('/')
def index():
    page = query_db('select * from page where path = "/"', one=True)
    return render_template('page.html', page=page, bread=[''])

@app.route('/<path>')
def page(path=None):
    page = query_db('select * from page where path = "%s"' % path, one=True)
    bread = Bread(path)
    return render_template('page.html', page=page, crumbs=bread.links)

I already feel like I'm violating DRY for having two functions there. But doing navigation will violate it further, since I also want the navigation on things like error pages.

But I can't seem to find a particularly Flasky way to do this. Any ideas?

解决方案

The "flasky" and pythonic way will be to use class-based view and templates hierarchy

First of all read documentation on both, then you can refactor your code based on this approach:

class MainPage(MethodView):
    navigation=False
    context={}

    def prepare(self,*args,**kwargs):
        if self.navigation:
            self.context['navigation']={
                #building navigation
                #in your case based on request.args.get('page')
            }
        else:
            self.context['navigation']=None

    def dispatch_request(self, *args, **kwargs):
        self.context=dict() #should nullify context on request, since Views classes objects are shared between requests
        self.prepare(self,*args,**kwargs)
        return super(MainPage,self).dispatch_request(*args,**kwargs)

class PageWithNavigation(MainPage):
    navigation = True

class ContentPage(PageWithNavigation):
    def get(self):
        page={} #here you do your magic to get page data
        self.context['page']=page
        #self.context['bread']=bread
        #self.context['something_Else']=something_Else
        return render_template('page.html',**self.context)

Then you can do following: create separate pages, for main_page.html and page_with_navigation.html Then your every page "error.html, page.html, somethingelse.html" based on one of them. The key is to do this dynamically:

Will modify prepare method a bit:

def prepare(self):
        if self.navigation:
            self.context['navigation']={
                #building navigation
                #in your case based on request.args.get('page')
            }
        else:
            self.context['navigation']=None
        #added another if to point on changes, but you can combine with previous one
        if self.navigation:
            self.context['extends_with']="templates/page_with_navigation.html"
        else:
            self.context['extends_with']="templates/main_page.html"

And your templates: main_page.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    {% block navigation %}
    {% endblock %}
    {% block main_content %}
    {% endblock %}
</body>
</html>

page_with_navigation.html

{% extends "/templates/main_page.html" %}

{% block navigation %}
        here you build your navigation based on navigation context variable, which already passed in here
{% endblock %}

page.html or any other some_page.html. Keep it simple!
Pay attention to first line. Your view sets up which page should go in there and you can easily adjust it by setting navigation= of view-class.

{% extends extends_with %}

{% block main_content %}
        So this is your end-game page.
        Yo do not worry here about navigation, all this things must be set in view class and template should not worry about them
        But in case you need them they still available in navigation context variable
{% endblock %}

这篇关于Flask中的动态导航的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆