Flask with Chart.js Tutorial - การประยุกต์ใช้งานร่วมกันระหว่าง Flask และ Chart.js

ใช้งาน Flask (Python Micro Web Framework) ร่วมกับกับ Chart.js ในการทำกราฟและ dashboard

Flask with Chart.js Tutorial - การประยุกต์ใช้งานร่วมกันระหว่าง Flask และ Chart.js

ทำไมต้องใช้ Chart.js ร่วมกันกับ Flask Python Web Framework

ในบทความนี้เราจะมาทำการประยุกต์ใช้งาน Chart.js ร่วมกันกับ Flaskซึ่งเรียกได้ว่าเป็น stack ที่รวมกันแล้วค่อนข้างที่จะเซ็กซี่นิดหนึ่ง ที่พูดแบบนี้ก็เพราะว่าทั้งคู่เป็นเฟรมเวิร์คและไลบรารี่ที่สามารถสร้างงานของตัวเองได้อย่างรวดเร็ว Flask นั้นก็สามารถที่จะสร้างเว็บได้อย่างรวดเร็ว ส่วน **Chart.js**ก็สามารถที่จะสร้าง Chart เพื่อทำการแสดงผลข้อมูลได้อย่างรวดเร็วมาก ๆ พร้อมทั้งง่ายและสะดวกเช่นกัน ดังนั้นจึงเป็นการจับคู่ที่ค่อนข้างจะลงตัวเสียจริง ๆ

**ปล.**สามารถชมคลิป Flask with Chart.js ประกอบการเรียนเพิ่มเติมได้ที่ในช่องยูทูปของเราได้ เพิ่มเติมเลยครับ และบทความนี้สามารถประยุกต์ Chart.js เพื่อใช้งานกับ Django ได้เช่นกัน คอนเซ็ปต์เหมือนกัน

เริ่มต้นสร้างโปรเจคท์ Flask

ทำการสร้างไฟล์ app.py ขึ้นมาเพื่อเขียนโค้ดไพธอน

app.py

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def chart():
    
    return render_template('chart.html')

if __name__ =="__main__":
    app.run(debug=True)

render HTML ออกไปแสดงผล

ตอนนี้คือการ render หน้า HTML ออกไปแสดงผล โดยตั้งชื่อไฟล์ว่า chart.html โดยตอนนี้ยังไม่ได้ทำการสร้างไฟล์นี้ขึ้นมา โดยไม่รอช้าสร้างไฟล์นี้ขึ้นมาได้เลย

ก่อนที่จะสร้างไฟล์ ต้องทำการสร้างโฟลเดอร์ templates เพื่อใช้เก็บไฟล์ HTML ต่าง ๆ ซึ่งนี่ก็เป็นโครงสร้างของ Flask ที่ได้วางไว้แบบนี้ ซึ่งถ้าท่านใดที่เคยเขียน Django ก็จะพบว่ามันเหมือนกันเป๊ะเลยในโครงสร้างส่วนนี้


Bootstrap & Chart.js CDN

chart.html

<!DOCTYPE html>
<html>
<head>
    <title>Chart.js with Flask</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
</head>

<body>
    <div class="container">
        <h1>Flask with Chart.js Tutorial</h1>
    </div>
</body>
</html>

จะเห็นว่าผมได้มีการเรียกใช้งาน Chart.js CDN เข้ามาใช้นั่นก็คือ

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
</head>

Bootstrap CDN

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">

ตอนนี้เรายังไม่ได้ทำการแสดงผล Chart ยังเป็นเพียงแค่ข้อความ “Flask with Chart.js Tutorial”

เมื่อทำการรันเซิร์ฟเวอร์ จะได้ดังภาพด้านล่าง

จากนั้นไปที่ **Chart.js Document**และทำการก็อปปี้โค้ด Tutorial เบื้องต้นมาใช้ และวางไว้ภายในแท็ก ของไฟล์ chart.html

<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true
                }
            }]
        }
    }
});
</script>

อธิบายการทำงานของโค้ดของ Chart.js

อธิบายโค้ดในเบื้องต้นแบบคร่าว ๆ

```css

var ctx = document.getElementById(‘myChart’).getContext(‘2d’);


กำหนดตัวแปรที่มีชื่อว่า  ctx  และกำหนดไอดีชื่อว่า  "myChart"

```javascript
 type: 'bar'

type เราสามารถที่จะกำหนดประเภทของ Chart ให้เป็นประเภทต่าง ๆ ได้ตามต้องการ เช่น บาร์, ไลน์, โดนัท, เส้น ฯลฯ เป็นต้น ซึ่งจะเห็นว่ามันค่อนข้างที่จะสะดวกสุด ๆ ไปเลยครับ ในการเปลี่ยนประเภทของ chart

labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange']

**** labels คือส่วนของชื่อของข้อมูลในแต่ละชาร์จ

data: [12, 19, 3, 5, 2, 3]

data คือส่วนของข้อมูลของแต่ละชาร์จเป็นแบบ Array โดยเราสามารถทดสอบเปลี่ยนแปลงข้อมูลได้ตามต้องการเพื่อทดสอบ

backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],

backgroundColor คือสีของชาร์จแต่ละชาร์จที่กำหนดเป็นแบบ RGB เลือกใช้ได้ตามต้องการ

โดยสามารถศึกษาหรือดูโค้ดสีแต่ละสีตามต้องการได้ในเว็บนี้ คลิ๊ก

borderColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],

โดยเรานำโค้ดด้านบนมาวางไว้ในส่วนของแท็ก bodyของ HTML ได้เลย

app.py

from flask import Flask, render_template

app = Flask(__name__)

data = [5, 9, 10, 7, 15, 11]

@app.route('/')
def chart():  
    chart_data = data
    
    return render_template('chart.html', chart_data=chart_data)

if __name__ =="__main__":
    app.run(debug=True)

จากนั้นทำการรันเซิร์ฟเวอร์

$ python app.py

จะได้หน้า Chart


จะเห็นว่าได้ Bar Chart มาเรียบร้อยแล้ว แต่ขนาดยังไม่ได้สัดส่วนยังใหญ่เกินไป แก้ปัญหาโดยปรับขนาดโดยใช้ col-md-5 ของ Bootstrap เข้าไปในแท็ก

<div class="col-md-5">
    <canvas id="myChart" width="400" height="400"></canvas>
</div>


จะได้ Bar Chart ที่ดูขนาดสมส่วน อย่างที่ได้กล่าวไปด้านบนว่า เราสามารถที่จะเปลี่ยนสีของ Chart ได้ตามต้องการไม่ว่าจะเป็นสีพื้นหลัง backgroundnColor หรือเส้นขอบ boderColor ตามรหัสสี RGB ของแต่ละตัวได้เลย

ดึงข้อมูลจาก Back-end มาแสดงผล

ถึงขั้นตอนนี้แล้วหลายท่านอาจเกิดความสงสัย แล้วถ้าเราต้องการที่จะเปลี่ยนแปลงข้อมูลของ Chart เราต้องตามแก้โค้ดในไฟล์ HTML นี้ตลอดเลยหรือไม่ คำตอบคือไม่ครับ มันไม่ค่อย make sense เอาเสียเลยที่จะทำแบบนั้น ดังนั้นวิธีการที่ดีคือข้อมูลควรจะมาจาก Database, จาก API Services, etc. และเป็นแบบอัปเดตโดยอัตโนมัติ

สมมติว่าเราทำการดึงข้อมูลมาจาก Databaseที่อยู่ฝั่งหลังบ้าน แต่ในบทความนี้ยังไม่ได้ทำการสร้าง Database แต่ก็ไม่มีปัญหาครับ ทดสอบสร้างข้อมูลแบบ Fake Data ขึ้นมาเพื่อทดสอบเล่น ๆ ก่อนได้

สร้างข้อมูลเทียม (Fake data) ขึ้นมาเพื่อทดสอบ

สร้างข้อมูลขึ้นมาเพื่อทดสอบเก็บเป็นแบบ List เพื่อให้เข้ากันกับข้อมูลของ Chart ที่เป็นแบบ Array ในโค้ด JavaScript ของ Chart.js โดยกำหนดตัวแปรชื่อ data = […] เก็บข้อมูลจำนวน 6 members และทดสอบใส่เป็นข้อมูลปลอม ๆ ขึ้นมาเพื่อทดสอบกำหนดเป็น 10 ทุกตัว

data = [10, 10, 10, 10, 10, 10]

ส่งข้อมูลออกไปแสดงผลในหน้า HTML

app.py

# Fake data
data = [10, 10, 10, 10, 10, 10]

@app.route('/')
def chart(): 
    chart_data = data
    
    return render_template('chart.html', chart_data=chart_data)

ตอนนี้ข้อมูลที่อยู่ในตัวแปร data ซึ่งก็คือ 10 ที่อยู่ใน members ทั้ง 6 ตัวของ List หลายท่านอาจจะสงสัยว่าทำไมต้องใช้ 10 เหมือนกันทุกตัว คำตอบก็คือผมอยากให้ตัว Chart นั้นดูง่ายครับว่ามันเป็นข้อมูลเดิมที่มากับ Chart หรือเป็นข้อมูลของเราที่สร้างขึ้นมาใหม่จากฝั่ง Backend คือ Flask แล้วส่งไปแสดงผล ดังนั้นการใช้ข้อมูลเหมือนกันจะทำให้ดูง่ายถ้าตัว Chart อยู่ในระนาบเดียวกันแสดงว่าข้อมูลของเราแสดงผลใน Chart ได้สำเร็จครับ

loop ข้อมูลออกมาแสดงผลใน Chart

คำถามต่อมาคือเราจะแสดงผลข้อมูลใน Chart ได้ยังไง คำตอบก็คือ ใช้การวนลูปข้อมูลเหมือนที่เคยทำใน Flask โปรเจคท์ที่ผ่าน ๆ ได้เลยเพราะว่าข้อมูลเป็นแบบ List ก็ต้องใช้ for loopนั่นเองครับ

chart.html

data: [12, 19, 3, 5, 2, 3]

จากโค้ดด้านบนคือข้อมูลเดิมที่มากับ Chart.js แต่ข้อมูลตรงนี้เราจะไม่ใช้อีกต่อไป จะเป็นการลูปข้อมูลที่ส่งมาจากฝั่ง Backend แทนครับ ทำได้โดยการวนลูปออกมาได้เลย โดยใช้ Jinja2 Templateของ Flask ตามปกติ ซึ่งหลายท่านอาจจะสงสัยว่า ตรงส่วนนี้มันเป็นโค้ดของ JavaScript เราจะใช้ Jinja2 Template ได้หรือไม่เพราะว่าเคยใช้ในส่วนของ HTML เท่านั้น คำตอบก็คือทำได้สบาย ๆ เหมือนกันเลยครับ โดยขอเสริม Jinja Template แบบคร่าว ๆ สักหน่อยเพื่อเป็นการทบทวนสำหรับใคร ๆ หลายคนครับ

{% %} –> คือ Tag เอาไว้ใช้เขียนคำสั่งหรือลอจิกต่าง ๆ

{{ }} –> คือ Variable เอาไว้ใช้แสดงผลข้อมูล

ทำการลูปข้อมูลออกมาแสดงผล

 data: [{% for dt in chart_data %} {{dt}} {% endfor %}],

โดย chart_data คือข้อมูลที่ส่งมาจากฝั่ง Backend ในฟังก์ชัน render_template นั่นเอง

จากนั้่นทำการรีเฟรชหน้าเว็บ


Inspect ดูข้อผิดพลาด

จะเห็นว่าตอนนี้ Chart ก็ยังไม่แสดงผล แสดงว่าต้องมีบางอย่างผิดพลาด ตรวจสอบได้โดยการคลิ๊กขวา Inspectหรือตรวจสอบที่หน้าเพจนี้


เมื่อทำการ Inspect ดู จะพบว่าข้อมูลนั้นถูกส่งมาไม่มีปัญหา เมื่อเปรียบเทียบกับข้อมูลที่ได้ทำการคอมเมนต์ไว้ด้านบน แต่เพียงแค่ไม่ถูกฟอร์แมตเท่านั้นครับคือ ข้อมูลคือ 10 ที่อยู่ใน Array นั้นไม่มีคอมม่ามาคั่น ทำการแก้ไขใหม่โดยเพิ่มคอมม่าเข้าไปหลัง Variable Tag คือ {{ dt }}

เพิ่ม , คอมม่าเข้ามา

 data: [{% for dt in chart_data %} {{dt}}, {% endfor %}],

จากนั้นทำการรีเฟรชหน้าเว็บอีกครั้ง


Flask + Chart.j Final Source Code

app.py

```python

from flask import Flask, render_template

app = Flask(name)

Fake data

data = [10, 10, 10, 10, 10, 10]

@app.route(‘/’) def chart():

# Assign data created above into a new variable 
# called "chart_data" then send it to frontend(HTML)
# to display on Bar Chart
chart_data = data

return render_template('chart.html', chart_data=chart_data)

if name ==“main”: app.run(debug=True)


## chart.html

## ```markup
<!DOCTYPE html>
<html>
<head>
    <title>Chart.js with Flask</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
</head>
<body>
    <div class="container">
        <h1>Flask with Chart.js Tutorial</h1>
        <div class="col-md-5">
            <canvas id="myChart" width="400" height="400"></canvas>
        </div>
    </div>

    <script>
    var ctx = document.getElementById('myChart').getContext('2d');
    var myChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
            datasets: [{
                label: '# of Votes',
                // data: [12, 19, 3, 5, 2, 3],
                data: [{% for dt in chart_data %} {{dt}}, {% endfor %}],
                backgroundColor: [
                    'rgba(255, 99, 132, 0.2)',
                    'rgba(54, 162, 235, 0.2)',
                    'rgba(255, 206, 86, 0.2)',
                    'rgba(75, 192, 192, 0.2)',
                    'rgba(153, 102, 255, 0.2)',
                    'rgba(255, 159, 64, 0.2)'
                ],
                borderColor: [
                    'rgba(255, 99, 132, 1)',
                    'rgba(54, 162, 235, 1)',
                    'rgba(255, 206, 86, 1)',
                    'rgba(75, 192, 192, 1)',
                    'rgba(153, 102, 255, 1)',
                    'rgba(255, 159, 64, 1)'
                ],
                borderWidth: 1
            }]
        },
        options: {
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true
                    }
                }]
            }
        }
    });
    </script>

</body>
</html>

สำหรับบทความ การประยุกต์ใช้งาน Flask with Chart.js Tutorial ก็ขอจบลงเพียงเท่านี้ ผมหวังเป็นอย่างยิ่งว่าเพื่อน ๆ ที่อ่านบทความนี้จบแล้ว จะเข้าใจคอนเซ็ปต์และนำไปต่อยอดเพิ่มเติมได้เป็นอย่างดีนะครับ เช่นการสร้าง Dashboard ต่าง ๆ การทำ Data Visualization เป็นต้น

ถ้าถูกใจบทความนี้ก็อย่าลืมคอมเมนต์เข้ามาที่ด้านล่างของบทความนี้เพื่อซัพพอร์ตและให้กำลังใจผลงานการเขียนของผมกันได้เลยนะครับ จะขอบคุณมาก ๆ ครับ

Follow us on

Medium:STACKPYTHON

Youtube:STACKPYTHON

Facebook: STACKPYTHON

หรือเข้าชมคอร์ส Flask Full Course ของ STACKPYTHON

Python Web Development with Flask Crash Course