Django + MySQL Dashboard 網頁端資料庫視覺化
1. Overview
Python + MySQL + Django, 有些資料託管在 MySQL 的資料庫,然後我們希望進行視覺化,通過 web 的方式對資料庫的資訊去進行展示/檢索/維護/..
這個專案中,我們的資料託管在 MySQL 的資料庫中,然後在 Django 中配置資料庫資訊,連線到資料庫,在前端用 Django-table2 進行渲染;
最終我們可以在 web 端看到如下所示效果,可以進行展示所有的資料,然後進行檢索和過濾;
我這邊爬了一些新聞下來,放到資料庫裡面,然後在前端 web 顯示後端 MySQL 資料庫中的新聞 (Time + Title + Category);
支援 search 和 filter 功能,支援下載介面內容到 CSV 功能;
2. 流程
想要在 Django 中訪問 MySQL 資料庫的資料,首先要在 Django 的 setting.py 裡面規定好資料庫的 'Name' / 'USER' / 'PASSWORD';
需要對於物件 news 或者別的實體,建立 model, 下圖中的 step4;
利用 Django-tables2 進行渲染,具體 Django-tables2 的使用可以參考 https://django-tables2.readthedocs.io/en/latest/pages/tutorial.html ;
過濾/搜尋/排序 都可以在後端,變成對 query 的操作,如 step6 ;
3. 原始碼
程式碼託管在 github, 在 Ubuntu host:
git clone https://github.com/coneypo/Django_MySQL_Table
前端程式碼 index.html
{% load render_table from django_tables2 %} {% load querystring from django_tables2 %} {% load bootstrap3 %} <!doctype html> <html> <head> <a href="board/"><title>Django table example</title></a> <link rel="stylesheet" href="/static/css/pos.css"/> <link rel="stylesheet" href="/static/css/bootstrap.min.css"/> <link rel="stylesheet" href="/static/css/table_1.css"/> <style> body {background-color: whitesmoke;} </style> <script type="text/javascript" src="/static/js/jquery-1.11.0.js"></script> </head> <body> <div id="Top" style="background:#38c"> <a href="/table_example" id="acrn_title"> Django-MySQL example -- coneypo</a> </div> <div id="Center"> <div id="Center_Searcher"> <form action="/news_search" method="get"> <table class="center_table"> <tr><td colspan="5"><h3>Search by Title</h3></td></tr> <tr> <td>Keyword:</td> <td align="center"> <input name="keywd_input" value="{{ keywd_input }}"></td> <td align="center"> <input type="submit" value="search"></td> </tr> </table> </form> </div> <div id="Center_Filter"> <form action="/news_filter" method="get"> <table class="center_table"> <tr><td colspan="5"><h3>Filter</h3></td></tr> <tr> <td>Category:</td> <td> <select name="filter_category"> {% for i in category_list %} <option value="{{i}}" {% if i == filter_category %} selected{% endif %}>{{i}}</option> {% endfor %} </select></td> <td><input type="submit" value="Filter"></td> </tr> </table> </form> </div> </div> <div id="Table"> <h3> Device table</h3> <form action="/download_excel" method="get"> <a href="/download_excel">Download to excel</a> </form><br> {% render_table table %} </div> </div> </body> </html>
後端 Django 檢視程式碼 views.py
1 from django.shortcuts import render 2 from django.db import models 3 from django.http import HttpResponse 4 import django_tables2 as tables 5 import MySQLdb 6 import datetime 7 import pytz 8 from django_tables2.config import RequestConfig 9 import itertools 10 from django.db import connection 11 from djqscsv import render_to_csv_response 12 13 ##### Modify with your database here ##### 14 db = MySQLdb.connect("localhost", "root", "intel@123", "ithome_news", charset='utf8') 15 cursor = db.cursor() 16 17 category_list = ['All', 'iPhone應用推薦', 'iPhone新聞', 'Win10快訊', 'Win10裝置', '業界', '人工智慧', '人物', '天文航天', '奇趣電子', '安卓應用推薦', 18 '安卓手機', '安卓新聞', '影像器材', '新能源汽車', '智慧家居', '智慧家電', '活動互動', '遊戲快報', '電商', '電子競技', '電腦硬體', '科技前沿', '科普常識', 19 '筆記本', '網路', '蘋果', '車聯網', '軟體快報', '辣品廣告', '通訊'] 20 21 22 class news(models.Model): 23 time = models.CharField(max_length=10, blank=True, null=True) 24 title = models.CharField(max_length=10, blank=True, null=True) 25 category = models.CharField(max_length=200, blank=True, null=True) 26 27 class Meta: 28 db_table = "news" 29 30 31 class newsTable(tables.Table): 32 counter = tables.Column(verbose_name="No", empty_values=(), orderable=False) 33 time = tables.Column(verbose_name="Time") 34 title = tables.Column(verbose_name="Title") 35 category = tables.Column(verbose_name="Category") 36 37 def render_counter(self): 38 self.row_counter = getattr(self, 'row_counter', itertools.count(1)) 39 return next(self.row_counter) 40 41 class Meta: 42 model = news 43 attrs = { 44 "class": "info-table", 45 } 46 fields = ("counter", "time", "title", "category") 47 48 49 def to_render(html_render, data, table): 50 html_render['table'] = table 51 html_render['category_list'] = category_list 52 53 54 def table_show(request): 55 data = news.objects.all() 56 data = data.values('time', 'title', 'category') 57 58 table = newsTable(data) 59 RequestConfig(request, paginate={'per_page': 100}).configure(table) 60 61 html_render = {} 62 to_render(html_render, data, table) 63 return render(request, "index.html", html_render) 64 65 66 # rendering "Search by Title" 67 def news_search(request): 68 data = news.objects.all() 69 html_render = {} 70 71 data = data.filter(models.Q(title__icontains=request.GET['keywd_input'])) 72 data = data.values("time", "title", "category") 73 table = newsTable(data) # , order_by="-time") 74 RequestConfig(request, paginate={'per_page': 100}).configure(table) 75 to_render(html_render, data, table) 76 html_render['keywd_input'] = request.GET['keywd_input'] 77 78 return render(request, "index.html", html_render) 79 80 81 # rendering "Filter" 82 def news_filter(request): 83 data = news.objects.all() 84 html_render = {} 85 86 if request.GET['filter_category'] == 'All': 87 pass 88 else: 89 data = data.filter(models.Q(category__icontains=request.GET['filter_category'])) 90 91 data = data.values("time", "title", "category") 92 table = newsTable(data) 93 RequestConfig(request, paginate={'per_page': 100}).configure(table) 94 to_render(html_render, data, table) 95 html_render['filter_category'] = request.GET['filter_category'] 96 97 return render(request, "index.html", html_render) 98 99 100 def download_excel(requst): 101 data = news.objects.all() 102 print(type(data)) 103 data = data.values("time", "title", "category") 104 print(type(data)) 105 return render_to_csv_response(data, filename="table_download.csv")
具體來看這塊,我加了註釋:
# 宣告 django.db 的 model class news(models.Model): time = models.CharField(max_length=10, blank=True, null=True) title = models.CharField(max_length=10, blank=True, null=True) category = models.CharField(max_length=200, blank=True, null=True) class Meta: # 宣告 MySQL 中 table 的名字,要不然可能會找不到 db_table = "news" # 宣告 django-tables2 的 table class newsTable(tables.Table): # verbose_name=顯示名稱 counter = tables.Column(verbose_name="No", empty_values=(), orderable=False) time = tables.Column(verbose_name="Time") title = tables.Column(verbose_name="Title") category = tables.Column(verbose_name="Category") # 用來渲染第一列的計數器 def render_counter(self): self.row_counter = getattr(self, 'row_counter', itertools.count(1)) return next(self.row_counter) class Meta: model = news attrs = { # 宣告 table 要呼叫的 CSS 樣式 "class": "info-table", } fields = ("counter", "time", "title", "category")
用 djqscsv 來實現匯出到 CSV:
from djqscsv import render_to_csv_response def download_excel(requst): data = news.objects.all() print(type(data)) data = data.values("time", "title", "category") print(type(data)) return render_to_csv_response(data, filename="table_download.csv")
urls.py 中繫結好連結:
urlpatterns = [ path('table_example', views.table_show), url(r'^news_search$', views.news_search), url(r'^news_filter$', views.news_filter), url(r'^download_excel', views.download_excel), ]
4. 配置
在 run Django server 之前,需要進行一些配置:
4.1 在本地 MySQL 資料庫中新增 ithome_news 這個 database;
mysql> create database ithome_news; mysql> use ithome_news; mysql> source /home/con/code/python/Django_MySQL_Table/ithome_news.sql
4.2 修改 Django 中 setting.py 中的 database 的配置,與你本地的資料庫 NAME / USER / PASSWORD 一致:
# Database DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'ithome_news', 'USER': 'root', ######## modify with your password here ######## 'PASSWORD': 'pwd', ################################################ 'CONN_MAX_AGE': 3600, } }
4.3 啟動 MySQL 伺服器
python3 manage.py runserver 8000
開啟本地網站 http://127.0.0.1:8000/table_example
或者
python3 manage.py runserver 0.0.0.0:port # 比如
python3 manage.py runserver 0.0.0.0:8777
開啟本地網站 http://[本機IP]:[port]/table_example, 同一路由下也可以訪問到該網站;
所以可以用來搭建 lab 內裝置管理系統 / 人員登記 / KPI 展示 前端 web 網頁;
# 請尊重他人勞動成果,轉載或者使用原始碼請註明出處:http://www.cnblogs.com/AdaminXie
# 如果對您有幫助,歡迎在 GitHub 上 Star 支援下: https://github.com/coneypo/Django_MySQL_Table
# 如有問題請留言或者聯絡郵箱 [email protected],商業合作