2016-03-28 54 views
6

有關處理「下一個」URL的文檔Flask-login。這個想法似乎是:如何通過使用Flask和Flask登錄的「下一個」URL?

  1. 用戶進入/some-secret-URL
  2. 用戶被重定向到登錄頁面(如/login
  3. 成功登錄後,用戶被重定向回/some-secret-URL

我找到的唯一使用Flask登錄的半完整示例是https://gist.github.com/bkdinoop/6698956。這很有幫助,但由於它不包含HTML模板文件,因此我看到我是否可以將它們重新創建爲自我訓練練習。

這裏的/secret/login部分的簡化版本:

@app.route("/secret") 
@fresh_login_required 
def secret(): 
    return render_template("secret.html") 

@app.route("/login", methods=["GET", "POST"]) 
def login(): 
    <...login-checking code omitted...> 
    if user_is_logged_in: 
     flash("Logged in!") 
     return redirect(request.args.get("next") or url_for("index")) 
    else: 
     flash("Sorry, but you could not log in.") 
     return render_template("login.html") 

而這裏的login.html

<form name="loginform" action="{{ url_for('login') }}" method="POST"> 
Username: <input type="text" name="username" size="30" /><br /> 
Password: <input type="password" name="password" size="30" /><br /> 
<input type="submit" value="Login" /><br /> 

現在,當用戶訪問/some-secret-URL,他被轉到/login?next=%2Fsecret。到目前爲止,這麼好 - 查詢字符串中的「next」參數。

但是,當用戶提交登錄表單時,他將被重定向回索引頁面,而不是返回到/secret URL。

我猜的原因是因爲傳入網址上可用的「下一個」參數沒有合併到登錄表單中,因此在處理表單時沒有作爲變量傳遞。 ?解決這個正確的方式

一個解決方案似乎工作 - 從

<form name="loginform" action="{{ url_for('login') }}" method="POST"> 

<form>標籤更改爲:

<form name="loginform" method="POST"> 

刪除「action」屬性後,瀏覽器(至少Windows上的Firefox 45)會自動使用當前URL,使其繼承?next=%2Fsecret查詢字符串,該查詢字符串已成功將其發送到表單處理處理程序。

但省略了「action」表單屬性並讓瀏覽器將其填充到正確的解決方案中嗎?它是否適用於所有瀏覽器和平臺?

或者Flask或Flask-login打算以不同的方式處理它?

+0

當你把'action =「{{url_for('login')}}」'的HTML源代碼輸出到底是什麼? –

+0

http://flask.pocoo.org/snippets/63/ – davidism

+0

@K DawG,它是'

' –

回答

4

如果您需要在表單中指定不同的動作屬性,則不能使用由Flask-Login提供的下一個參數。無論如何,我建議將端點而不是URL放入url參數中,因爲它更容易驗證。以下是我正在處理的應用程序中的一些代碼,也許這可以幫助您。

覆蓋燒瓶登錄的未經授權的處理程序使用的終端,而不是URL中的下一個參數:

@login_manager.unauthorized_handler 
def handle_needs_login(): 
    flash("You have to be logged in to access this page.") 
    return redirect(url_for('account.login', next=request.endpoint)) 

使用request.endpoint在自己的網址,太:

{# login form #} 
<form action="{{ url_for('account.login', next=request.endpoint) }}" method="post"> 
... 
</form> 

重定向到端點下一個參數(如果存在且有效),否則重定向到後備。

def redirect_dest(fallback): 
    dest = request.args.get('next') 
    try: 
     dest_url = url_for(dest) 
    except: 
     return redirect(fallback) 
    return redirect(dest_url) 

@app.route("/login", methods=["GET", "POST"]) 
def login(): 
    ... 
    if user_is_logged_in: 
     flash("Logged in!") 
     return redirect_dest(fallback=url_for('general.index')) 
    else: 
     flash("Sorry, but you could not log in.") 
     return render_template("login.html") 
+0

在我使用的表單中:next = request.args.get(「next」)。在redirect_dest中,它應該是dest = request.args.get(「next」) – 2ni

+0

@ 2ni在我的例子中,表單顯示在每一頁的頂部,如果你想要一個單獨的登錄頁面,你應該使用'next = request。 args.get( 「下一步」)'。修正你的第二個提到,謝謝。 – timakro

0

@timakro提供了一個整潔的解決方案。 如果你想處理一個動態鏈接如

指數/ <用戶>

然後使用Request的,而不是因爲request.endpoint將不包含動態vairable信息:

@login_manager.unauthorized_handler 
def handle_needs_login(): 
    flash("You have to be logged in to access this page.") 
    return redirect(url_for('account.login', next=request.path)) 

以下代碼應更改爲:

def redirect_dest(home): 
    dest_url = request.args.get('next') 
    if not dest_url: 
     dest_url = url_for(home) 
    return redirect(dest_url) 

@app.route("/login", methods=["GET", "POST"]) 
def login(): 
    ... 
    if user_is_logged_in: 
     flash("Logged in!") 
     return redirect_dest(home=anyViewFunctionYouWantToSendUser) 
    else: 
     flash("Sorry, but you could not log in.") 
     return render_template("login.html") 
相關問題