Flask Login/Logout — สร้างระบบ Authentication Systems — Ep.3 — Logout, Message Flashing(Ep สุดท้าย)

stackpython
4 min readNov 3, 2020

หลังจากทั้ง 2 EPs ที่ผ่านมาได้ทำระบบ Login และทำความเข้าใจกระบวนการต่าง ๆ ไปพอสมควร จนเกือบจะสมบูรณ์กันแล้วครับ แต่จะยังคงเหลือระบบอีกบางส่วนครับ แต่ก็เหลือไม่เยอะแล้ว คือเหลือ Logout และการทำ Message Flashing ซึ่งหลายท่านอาจจะยังงง ๆ อยู่ว่า Message Flashing มันคืออะไร ใน Ep นี้มีคำตอบครับ

จุดประสงค์

  • เข้าใจและสามารถสร้างฟังก์ชันเพื่อทำการ Logout ออกจากระบบได้
  • เข้าใจและสามารถใช้งานการทำ Message Flashing ซึ่งเป็นฟีเจอร์ที่จะช่วยให้ฟีดแบ็คแก่ผู้ใช้ ซึ่งจะช่วยสร้างประสบการณ์การใช้งานของผู้ใช้ (User Experience) ที่ดียิ่งขึ้น
  • ประยุกต์ใช้งาน Bootstrap Alert Cards และสามารถเลือกแสดงผล Message Flashing ให้แจ้งเตือนตามแต่ละประเภทได้ เช่นถ้ามีการลบข้อมูลหรือหรือล็อกอินไม่ถูกต้องให้แจ้งเตือนเป็นการ์ดสีแดง(danger) ถ้ามีการสร้างโพสต์ใหม่หรือล็อกอินสำเร็จให้แจ้งเตือนด้วยการ์ดสีเขียว(success) เป็นต้น

หลังจากใน Ep.1 และ Ep.2 ได้ทำการล็อกอินไปเรียบร้อย พร้อมทั้งเรียนรู้โพรเซสทีสำคัญและเกี่ยวข้องทุกส่วนแล้ว ในบทความนี้ก็จะเป็นบทความสุดท้ายในซีรีย์นี้กันแล้วครับ

Logout

หลังจากตอนนี้เราได้ทำการล็อกอินเข้าหน้าเว็บเรียบร้อย แต่ติดปัญหาคือ ไม่สามารถล็อกเอาท์ออกมาได้ ดังนั้นเราจะมาเขียนฟังก์ชันเพื่อทำการ Logout กันครับ

ซึ่งฟังก์ชัน Logout นี้ก็ค่อนข้างที่จะเขียนง่าย ๆ ด้วยโค้ดเพียงแค่ไม่กี่บรรทัดและมีขั้นตอนไม่เยอะเหมือนล็อกอินครับที่ต้องทำการเช็คค่านั่นนี่ โดยการล็อกเอาท์ก็ทำได้โดยการคลิ๊กปุ่มเพื่อไปทริกฟังก์ชัน logout เพียงเท่านี้

ซึ่งตัวฟังก์ชัน logout_user เราก็ได้ทำการอิมพอร์ตเข้ามาใช้งานเรียบร้อยแล้วใน Ep.2 ที่ผ่านมา

from flask_login import ... logout_user

ดังนั้นเริ่มเขียนฟังก์ชันใน app.py กันต่อ

# app.py...@app.route("/logout")@login_requireddef logout():
logout_user() return redirect(url_for('login'))...

เมื่อเขียนฟังก์ชัน logout เสร็จเรียบร้อยแล้ว จะเห็นว่าเราได้ทำการเรียกใช้งานฟังก์ชันที่เป็นพระเอกของหัวข้อนี้เลยก็คือ logout_user เข้ามาใช้งานได้แบบสะดวกมากมาย จากนั้นเมื่อมีการ logout สำเร็จให้มีการ redirect ไปที่หน้า login ซึ่งเป็นโปรเซสอย่างที่ควรจะเป็นครับ

base.html

จากนั้นใน base.html ก็ทำการเพิ่มฟังก์ชัน logout เข้าไป

<a class="dropdown-item" href="{{url_for('logout')}}">Log out</a>

กำหนดการแสดงผล Login, Logout และ Sign up ใน Dropdown

ในตอนนี้ User ยังไม่ได้มีการล็อกอิน ซึ่งจุดประสงค์ที่ผมกำลังจะทำคือในส่วนของ Dropdown menu ของ Bootstrap จะมี 2 กรณีคือ

  • แสดงผลเฉพาะ Log in กับ Sign up เท่านั้น จะไม่ให้แสดงผล Log out เนื่องจากว่า User ยังไม่ได้ล็อกอิน ดังนั้นไม่จึงไม่ make sense ที่จะแสดง Log out
  • แสดงผล Log out เท่านั้นเมื่อ User มีการล็อกอินเข้าใช้งานแล้ว

โดยเราจะใช้ตัวเงื่อนไขด้านล่างนี้ครับเหมือนที่เคยทำใน Ep ที่ผ่านมา โดยใช้ if-else คือใช้แท็ก {% if current_user.is_authenticated %} แล้วทำการกำหนด statements ของ HTML ตามที่ต้องการ

  • ถ้า User ยังไม่ได้ล็อกอิน ให้แสดงผล Sign up และ Log in
  • ถ้า User ล็อกอินเรียบร้อย ให้แสดงผลเฉพาะ Log out

ซึ่งจะได้โค้ด HTML ตามด้านล่างนี้

<!-- base.html -->...<div class="dropdown-menu" aria-labelledby="navbarDropdown">  {% if current_user.is_authenticated %}    <a class="dropdown-item" href="/logout">Log out</a>  {% else %}    <a class="dropdown-item" href="{{url_for('login')}}">Log in</a>    <div class="dropdown-divider"></div>      <a class="dropdown-item" href="{{url_for('sign_up')}}">Sign up</a>  {% endif %}</div>...

เงื่อนไขที่ 1 User ยังไม่ได้ล็อกอิน แสดงผลดังภาพด้านล่าง

ผู้ใช้ยังไม่ได้ทำการล็อกอิน

เงื่อนไขที่ 2 User ได้ทำการล็อกอินแล้ว แสดงผลดังภาพด้านล่าง

เมื่อผู้ใช้ทำการล็อกอินเข้ามาเรียบร้อย

Message Flashing

Flash เป็นการฟีดแบ็คข้อความกลับไปที่ผู้ใช้เพื่อบ่งบอกหรือตอบกลับข้อความบางอย่างออกไปแสดงผล เป็นสร้างสร้าง User Experience (UX)ที่ดีแก่ผู้ใช้ ซึ่งถ้าใครที่ยังมองภาพไม่ออก ผมได้แนบภาพด้านล่างเข้ามาประกอบครับ นี่แหละครับคือ Message Flashingโดย message หรือ ข้อความที่ได้ flash ออกไปแสดงผลคือ “Succesful Login” ซึ่งเป็นการย้ำหรือแสดงผลให้ผู้ใช้ทราบเพิ่มเติมว่า ได้ทำการล็อกอินสำเร็จนะ

Flash Message

ซึ่ง Flask ก็มีฟังก์ชัน flash ซึ่งเราได้ทำการอิมพอร์ตเข้ามาใช้งานในส่วนของโมดูล flask ใน Ep.2 ที่ผ่านมาซึ่งอยู่ในโค้ดบรรทัดแรกสุด

from flask import ... flash<!-- base.html -->...{% with messages = get_flashed_messages() %}  {% if messages %}    <ul class=flashes>      {% for message in messages %}        <li>{{ message }}</li>      {% endfor %}    </ul>  {% endif %}{% endwith %}
...

ทดสอบล็อกอิน เมื่อล็อกอินสำเร็จจะปรากฏข้อความที่ได้ทำการ flash ออกมา แต่ยังดูไม่สวยงาม ดูเรียบเกินไป

flash เพื่อแสดงผลข้อความออกมาได้แล้ว แต่ยังดูธรรมดา ราบเรียบเกินไป

เราจะใช้ Bootstrap Alert เข้ามาเพื่อช่วยให้ Message Flashing ดูสวยงาม โดยจะมี Alert ในรูปแบบต่าง ๆ ให้เลือกใช้ตามความเหมาะสม

ฺBootstrap Alert

Flash ตาม Category

ถึงตอนนี้เชื่อว่าหลาย ๆ คนสามารถทำ Message Flashing ได้แล้ว แต่คำถามสุดท้ายคือ ตอนนี้ทำได้เพียงแค่แจ้งเตือนแสดงผลได้แค่ Alert ประเภทเดียว แต่ถ้าเราต้องการจะทำให้ Alert หลาย ๆ รูปแบบเช่น ถ้า Log in สำเร็จ ให้แสดงผล Alert (Bootstrap) สีเขียวคือ success ถ้าล็อกอินผิดหรือไม่สำเร็จให้แสดงผล Alert สีแดงคือคลาส danger เป็นต้น

จากโค้ดด้านล่างได้ทำการ flash ข้อความไปแสดงผล จะเห็นว่ามีการในฟังก์ชัน flash( ) นั้นเราได้ทำการใส่ข้อความคือ “Successful Login” ซึ่งเป็นอากิวเมนต์ตัวแรกที่ได้ใส่เข้าไปในฟังก์ชันนี้

flash(“Successful Login”)

ซึ่งยังมีอากิวเมนต์อีกตัวที่เราสามารถใส่เข้าไปได้นั่นก็คือ “category” หรือประเภทหรือหมวดหมู่ของข้อความที่เราต้องการ flash ออกไปแสดงผลนั่นเอง

flash(“Successful Login”, "success")

ซึ่งตัว category คือ “success” ก็จะถูกแสดงผลที่ตัว Alert Card ของ Bootstrap

<div class="alert alert-{{ category }}" role="alert">{{ message }}</div>
Successful Login

จะเห็นได้ว่า ตอนนี้เราสามารถที่จะ flash ข้อความออกไปแสดงผลตามประเภทที่ต้องการได้แล้ว ซึ่งในตอนนี้ก็ถึงเวลาที่จะเลือกส่งออกไปตาม category ที่ต้องการ ถ้าเป็นข้อความประเภทที่ต้องการแสดงแจ้งเตือนเออเร่อหรือสีแดงเช่นถ้าล็อกอินไม่ถูกต้อง ก็ใช้

flash(“Invalid Login”, "danger")
Invalid Login

เพียงเท่านี้เราก็สามารถที่จะใช้การ flash ตาม category ได้แล้วครับ ส่วนเราจะแบ่ง category เป็นแบบไหนก็อยู่ที่เราจะดีไซน์กันได้ตามต้องการเลยครับ โดยหาฟังก์ชัน flash ในแอปของเราแล้วเพิ่ม category เข้าไปเป็นอากิวเมนต์ตัวที่สอง

ในตอนแรกในฟังก์ชัน get_flashed_messages( ) ไม่ได้มีการใส่อะไรเข้าไป ปล่อยเป็นค่า default แต่ในตอนนี้จะมีการ flash ตาม category ออกไป จึงต้องใส่ with_categories=true เข้ามาเพิ่ม

get_flashed_messages(with_categories=true )

โดยในโค้ดนี้จะทำการลูปทั้ง category และ message จาก messages ออกมาแสดงผล

{% for category, message in messages %}

การแสดงผลก็จะเปลี่ยนไปตาม category ที่ได้กำหนดไว้ในฟังก์ชัน flash

<div class="alert alert-{{ category }}" role="alert">{{ message }}</div>

flash with category final code

<!-- base.html -->...<div class='container' style="text-align: center;">  <hr>  {% with messages = get_flashed_messages(with_categories=true) %}    {% if messages %}      {% for category, message in messages %}        <div class="alert alert-{{ category }}" role="alert">          {{ message }}        </div>      {% endfor %}    {% endif %}  {% endwith %}</div>...
base.html

และนี่ก็คือไฟล์ app.py และ base.html

สำหรับ Flask-Login Ep.3 ซึ่งเป็นตอนสุดท้าย ก็ขอจบลงเพียงเท่านี้ครับ ถ้ามีคำถามหรือข้อสงสัยหรือไม่เข้าใจตรงไหนก็คอมเมนต์ได้ที่ด้านล่างบทความกันได้เลยครับ หรือถ้าอยากติชมหรือมีอะไรเสนอแนะก็คอมเมนต์เข้ามาได้เช่นกันครับ

Sonny STACKPYTHON

ท่านสามารถติดตามพวกเราได้ที่ stackpython ตามช่องทางด้านล่างนี้ได้เลยครับ

คอร์ส: Python Web Development with Flash Crash Course

Instagram: stackpython

Facebook: stackpython

Website: stackpython.co

YouTube: stackpython

References

Message Flashing

บทความแนะนำ

Flask message flashing | Pythonise

--

--