2013-03-19 168 views
4

我有一個非常簡單的工作在Flask中的站點,它們都是由sqlite數據庫提供的。每個頁面作爲一行存儲在頁面表中,該表格包含路徑,標題,內容等內容。Flask中的動態導航

該結構是分層結構,其中頁面可以具有父級。因此,例如,'約'可能是一個頁面,也可能是'關於/某事'和'關於/蛋糕'。因此,我想創建一個導航欄,並鏈接到所有具有「/」父項的鏈接(/是根頁面)。另外,我希望它也顯示已打開的頁面以及該頁面的所有父母。因此,舉例來說,如果我們在'about/cakes/muffins',除了總是顯示的鏈接,我們還會看到鏈接到'about/cakes',以某種方式如下:

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

帶有孩子的那些頁面的尾部斜線,沒有那些沒有孩子的頁面。

代碼:

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

我已經覺得我違反乾的有有兩種功能。但是做導航會進一步違反它,因爲我也想要導航錯誤頁面之類的東西。

但我似乎無法找到一個特別Flasky的方式來做到這一點。有任何想法嗎?

+2

對不起,我不完全確定你在這裏問什麼 - 怎麼做到底是什麼?您在「頁面」視圖中構建SQL查詢的方式不安全,並且面臨注入式攻擊。看看這裏的一些答案(http://stackoverflow.com/a/775399/1949092),看看如何安全地處理用戶輸入。 – DazWorrall 2013-03-19 14:04:10

+0

是的,這是所有臨時代碼,我知道SQL注入。我在問我如何在Flask中使用動態樹狀導航。我之前在使用mppt的django中完成了此操作,但我沒有在任何地方看到Flask等價物。 – 2013-03-19 14:08:19

+0

我有一個類似的問題,但另外需要導航才能訪問flask.session變量。見https://stackoverflow.com/questions/45948609/accessing-flask-session-variables-from-flask-navigation-for-dynamic-navigation-m – 2017-08-29 21:33:45

回答

5

的「flasky」和Python的方式將是使用基於類的視圖和模板層次

所有的

首先讀取兩個文件,那麼你就可以在此基礎上的方法重構代碼:

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) 

然後,你可以做以下操作: 創建單獨的頁面,main_ page.html和page_with_navigation.html 然後你的每一頁「error.html,page.html,somethingelse.html」基於其中之一。 關鍵是要動態地做到這一點:

將修改準備方法的位:

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" 

而且你的模板: 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或任何其他some_page.html。把事情簡單化!
注意第一行。您的視圖設置了哪些頁面應該放在那裏,您可以通過設置navigation = 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 %} 
2

你可以只是有多個裝飾做一個功能:)

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

個人而言,我會修改麪包功能,也爲路徑/的工作,雖然。

如果它只是有關添加變量到你的背景下,比我會建議看上下文處理器:http://flask.pocoo.org/docs/templating/#context-processors

+0

這不是我感興趣的麪包屑,這些工作已經。我在其餘的導航工作之後。 – 2013-03-19 14:07:16

+0

@Knyght:你看到關於上下文處理器的部分了嗎?那些應該能夠很好地爲你解決這個問題。只需編寫一個上下文處理器,根據給定的路徑(或請求)自動生成導航菜單,並且它應該可以工作。 – Wolph 2013-03-19 14:13:07

+0

另外,woops,我改變了bread()的工作方式,忘了更新第一個函數,這是你重複自己時得到的,derp。感謝多個裝飾者提示。我會研究環境處理器。謝謝。 – 2013-03-19 14:18:29