Python操作國產(chǎn)金倉數(shù)據(jù)庫KingbaseES全流程
前言
現(xiàn)在國產(chǎn)化替代是大趨勢,國產(chǎn)數(shù)據(jù)庫的應(yīng)用范圍越來越廣,金倉數(shù)據(jù)庫(KingbaseES)作為其中的佼佼者,在政務(wù)、金融等領(lǐng)域部署得特別多。今天我就帶大家從0到1,親手實(shí)現(xiàn)用Python操作KingbaseES數(shù)據(jù)庫,還會基于Flask框架搭一個可視化的網(wǎng)頁管理系統(tǒng),數(shù)據(jù)的增刪改查(CRUD)全流程都能覆蓋到,Python開發(fā)者和數(shù)據(jù)庫管理員跟著學(xué),都能掌握這套實(shí)用技能。
一、前置知識與環(huán)境準(zhǔn)備
開始動手前,咱們得把相關(guān)的環(huán)境和工具準(zhǔn)備好,這樣后面開發(fā)的時候才不會卡殼。
1.1 核心技術(shù)棧
這次做項目用的技術(shù)都不復(fù)雜,也不用復(fù)雜的框架,輕量化還好上手,具體有這些:
- 后端框架:Flask(這是個輕量級的Python Web框架,用來快速搭網(wǎng)頁服務(wù)特別方便)
- 數(shù)據(jù)庫驅(qū)動:psycopg2(KingbaseES兼容PostgreSQL協(xié)議,直接用這個驅(qū)動就能連接數(shù)據(jù)庫)
- 前端技術(shù):HTML + 原生CSS(不用額外學(xué)前端框架,咱們把核心功能實(shí)現(xiàn)了就行)
- 數(shù)據(jù)庫:KingbaseES V8/R3(我這次用的是比較常見的版本,其他版本操作步驟都一樣)
1.2 環(huán)境安裝步驟
步驟1:安裝Python(已經(jīng)裝了的話這步就跳過)
直接去Python官網(wǎng)下載3.7及以上版本,安裝的時候記得勾選“Add Python to PATH”,這樣后面在命令行里就能直接調(diào)用python和pip命令了。
步驟2:安裝依賴庫
打開命令行,輸下面這些命令,就能把項目需要的依賴庫裝好:
# 安裝Flask框架 pip install flask # 安裝KingbaseES數(shù)據(jù)庫驅(qū)動(兼容PostgreSQL) pip install psycopg2-binary
步驟3:確認(rèn)KingbaseES數(shù)據(jù)庫狀態(tài)
- 首先得確保KingbaseES數(shù)據(jù)庫已經(jīng)啟動了,而且能通過IP(比如本地的
127.0.0.1)和端口(默認(rèn)常用端口是54321)訪問到。 - 提前創(chuàng)建好數(shù)據(jù)庫,我這次用的是
TEST庫,大家可以用KingbaseES的圖形化工具KingbaseManager來創(chuàng)建。 - 還要準(zhǔn)備好數(shù)據(jù)庫的賬號密碼,我這里用的是默認(rèn)管理員賬號
system,密碼大家可以自己修改。
二、項目架構(gòu)設(shè)計
為了讓代碼結(jié)構(gòu)清晰,后面維護(hù)起來也方便,咱們采用“后端邏輯+前端模板”的分層設(shè)計,整個項目的目錄結(jié)構(gòu)是這樣的:
kingbase_web_manager/ # 項目根目錄
├── app.py # 后端核心邏輯(包含F(xiàn)lask服務(wù)、數(shù)據(jù)庫操作、路由定義)
└── templates/ # 前端HTML模板文件夾(用繼承式設(shè)計,減少重復(fù)代碼)
├── base.html # 基礎(chǔ)模板(放公共頭部、樣式、消息提示這些)
├── index.html # 首頁(用來展示用戶列表)
├── init_schema.html # 表結(jié)構(gòu)初始化頁面
├── create_user.html # 新增用戶頁面
├── user_detail.html # 用戶詳情頁面
└── update_balance.html # 余額修改頁面
- 后端:通過Flask定義路由,處理前端發(fā)來的HTTP請求,再調(diào)用
psycopg2去操作KingbaseES數(shù)據(jù)庫。 - 前端:用HTML模板繼承的方式,
base.html作為父模板,這樣所有頁面風(fēng)格能統(tǒng)一,也能少寫很多重復(fù)代碼。
三、后端核心實(shí)現(xiàn)(app.py)
后端就像是整個系統(tǒng)的“大腦”,負(fù)責(zé)連接數(shù)據(jù)庫、處理業(yè)務(wù)邏輯,最后把數(shù)據(jù)返回給前端。下面我分模塊給大家講核心代碼怎么寫。
3.1 初始化Flask與數(shù)據(jù)庫配置
首先創(chuàng)建app.py文件,先把Flask應(yīng)用初始化好,再配置KingbaseES數(shù)據(jù)庫的連接參數(shù):
from flask import Flask, jsonify, request, render_template, redirect, url_for, flash
import psycopg2 # KingbaseES數(shù)據(jù)庫驅(qū)動
import psycopg2.extras as extras # 擴(kuò)展功能(如DictCursor,讓查詢結(jié)果為字典格式)
# 初始化Flask應(yīng)用
app = Flask(__name__)
# 配置secret_key(用于flash消息提示,防止跨站請求偽造)
app.secret_key = 'kingbase_web_manager_2024'
# --------------------------
# KingbaseES數(shù)據(jù)庫連接配置
# --------------------------
DB_CFG = dict(
host="127.0.0.1", # 數(shù)據(jù)庫IP(本地為127.0.0.1,遠(yuǎn)程需填實(shí)際IP)
port=54321, # KingbaseES默認(rèn)常見端口(不同環(huán)境可能為5432,需確認(rèn))
dbname="TEST", # 數(shù)據(jù)庫名稱(提前創(chuàng)建好)
user="system", # 數(shù)據(jù)庫賬號(管理員賬號)
password="jcsjk520.",# 數(shù)據(jù)庫密碼(替換為你的實(shí)際密碼)
connect_timeout=5, # 連接超時時間(5秒)
)
# --------------------------
# 數(shù)據(jù)庫連接工具函數(shù)
# --------------------------
def get_conn():
"""獲取KingbaseES數(shù)據(jù)庫連接"""
try:
# 使用psycopg2.connect連接數(shù)據(jù)庫,**DB_CFG表示解包配置字典
conn = psycopg2.connect(**DB_CFG)
return conn
except Exception as e:
# 連接失敗時拋出異常(后續(xù)路由會捕獲處理)
raise Exception(f"數(shù)據(jù)庫連接失敗: {str(e)}")
3.2 表結(jié)構(gòu)初始化(建表)
第一次用的時候,得先創(chuàng)建用戶表(t_user),咱們可以通過/init-schema這個路由,在網(wǎng)頁端觸發(fā)建表操作:
@app.route('/init-schema', methods=['GET', 'POST'])
def init_schema():
"""初始化用戶表結(jié)構(gòu)(GET請求顯示頁面,POST請求執(zhí)行建表)"""
# 1. POST請求:用戶點(diǎn)擊"初始化"按鈕,執(zhí)行建表SQL
if request.method == 'POST':
# 定義建表SQL(if not exists確保表不存在時才創(chuàng)建,避免重復(fù)執(zhí)行報錯)
create_table_sql = """
create table if not exists t_user(
id serial primary key, # 自增主鍵(用戶ID)
name varchar(64) not null, # 用戶名(非空)
balance numeric(12,2) default 0, # 余額(默認(rèn)0,支持兩位小數(shù))
created_at timestamp default current_timestamp # 創(chuàng)建時間(默認(rèn)當(dāng)前時間)
);
"""
try:
# 使用with語句自動管理連接和游標(biāo)(無需手動關(guān)閉)
with get_conn() as conn, conn.cursor() as cur:
cur.execute(create_table_sql) # 執(zhí)行建表SQL
# 建表成功,通過flash傳遞成功消息(前端會顯示)
flash('表結(jié)構(gòu)初始化成功!', 'success')
except Exception as e:
# 建表失敗,傳遞錯誤消息
flash(f'初始化失敗: {str(e)}', 'danger')
# 無論成功與否,跳轉(zhuǎn)回首頁
return redirect(url_for('index'))
# 2. GET請求:顯示初始化表結(jié)構(gòu)的頁面
return render_template('init_schema.html')
3.3 用戶數(shù)據(jù)增刪改查實(shí)現(xiàn)
接下來咱們實(shí)現(xiàn)核心的CRUD功能,每個功能對應(yīng)一個路由,專門處理前端的請求,然后操作數(shù)據(jù)庫。
3.3.1 首頁:展示所有用戶(查-列表)
首頁/這個路由會查詢t_user表里的所有數(shù)據(jù),然后把數(shù)據(jù)傳給前端模板展示出來:
@app.route('/')
def index():
"""首頁:展示所有用戶列表"""
try:
# 查詢所有用戶數(shù)據(jù)(按ID升序,可選)
query_sql = "select id, name, balance, created_at from t_user order by id;"
# 使用DictCursor,讓查詢結(jié)果為字典(便于前端通過鍵名獲取值)
with get_conn() as conn, conn.cursor(cursor_factory=extras.DictCursor) as cur:
cur.execute(query_sql)
# fetchall()獲取所有結(jié)果,轉(zhuǎn)換為列表(每個元素是字典)
users = [dict(row) for row in cur.fetchall()]
# 渲染首頁模板,傳遞用戶列表數(shù)據(jù)
return render_template('index.html', users=users)
except Exception as e:
# 查詢失敗,顯示錯誤消息,傳遞空列表
flash(f'數(shù)據(jù)庫查詢錯誤: {str(e)}', 'danger')
return render_template('index.html', users=[])
3.3.2 新增用戶(增)
通過/user/create這個路由實(shí)現(xiàn)新增用戶的功能,還能讓用戶輸入用戶名和初始余額:
@app.route('/user/create', methods=['GET', 'POST'])
def create_user():
"""新增用戶(GET顯示表單,POST提交數(shù)據(jù))"""
if request.method == 'POST':
# 1. 獲取前端表單提交的數(shù)據(jù)(request.form用于獲取POST表單數(shù)據(jù))
name = request.form.get('name') # 用戶名(必填)
balance = request.form.get('balance', 0.0) # 初始余額(可選,默認(rèn)0)
# 2. 數(shù)據(jù)校驗(yàn):用戶名不能為空
if not name:
flash('用戶名不能為空!', 'danger')
return render_template('create_user.html') # 校驗(yàn)失敗,返回表單頁面
try:
# 3. 數(shù)據(jù)格式轉(zhuǎn)換:余額轉(zhuǎn)為浮點(diǎn)數(shù)(防止非數(shù)字輸入)
balance = float(balance) if balance else 0.0
# 4. 執(zhí)行插入SQL(returning id返回新增用戶的ID)
insert_sql = "insert into t_user(name, balance) values (%s, %s) returning id;"
with get_conn() as conn, conn.cursor() as cur:
cur.execute(insert_sql, (name, balance)) # %s為參數(shù)占位符(防止SQL注入)
user_id = cur.fetchone()[0] # 獲取返回的用戶ID
# 5. 新增成功,跳轉(zhuǎn)回首頁
flash(f'用戶創(chuàng)建成功!用戶ID: {user_id}', 'success')
return redirect(url_for('index'))
except ValueError:
# 余額非數(shù)字時捕獲異常
flash('初始余額必須為數(shù)字!', 'danger')
except Exception as e:
# 其他錯誤(如數(shù)據(jù)庫異常)
flash(f'用戶創(chuàng)建失敗: {str(e)}', 'danger')
# GET請求:顯示新增用戶表單
return render_template('create_user.html')
3.3.3 查看用戶詳情(查-單條)
通過用戶ID查詢單條用戶數(shù)據(jù),然后展示詳細(xì)信息:
@app.route('/user/<int:user_id>')
def get_user(user_id):
"""查看單個用戶詳情(通過URL路徑傳遞user_id)"""
try:
# 查詢指定ID的用戶數(shù)據(jù)
query_sql = "select id, name, balance, created_at from t_user where id=%s;"
with get_conn() as conn, conn.cursor(cursor_factory=extras.DictCursor) as cur:
cur.execute(query_sql, (user_id,)) # 傳遞user_id參數(shù)
user = dict(cur.fetchone()) if cur.rowcount > 0 else None # 轉(zhuǎn)換為字典
# 校驗(yàn)用戶是否存在
if not user:
flash('該用戶不存在!', 'danger')
return redirect(url_for('index')) # 不存在則跳轉(zhuǎn)回首頁
# 渲染詳情頁面,傳遞用戶數(shù)據(jù)
return render_template('user_detail.html', user=user)
except Exception as e:
flash(f'查詢用戶失敗: {str(e)}', 'danger')
return redirect(url_for('index'))
3.3.4 修改用戶余額(改)
通過/user/<user_id>/balance這個路由調(diào)整用戶余額,不管是增加還是減少都能實(shí)現(xiàn):
@app.route('/user/<int:user_id>/balance', methods=['GET', 'POST'])
def update_balance(user_id):
"""修改用戶余額(GET顯示表單,POST提交修改)"""
if request.method == 'POST':
try:
# 1. 獲取余額變動值(delta:正數(shù)增加,負(fù)數(shù)減少)
delta = float(request.form.get('delta', 0))
# 2. 執(zhí)行更新SQL(balance = balance + %s 實(shí)現(xiàn)增量更新)
update_sql = "update t_user set balance = balance + %s where id=%s;"
with get_conn() as conn, conn.cursor() as cur:
cur.execute(update_sql, (delta, user_id))
# 校驗(yàn)用戶是否存在(rowcount為受影響行數(shù),0表示無此用戶)
if cur.rowcount == 0:
flash('該用戶不存在!', 'danger')
return redirect(url_for('index'))
# 3. 更新成功,跳轉(zhuǎn)回用戶詳情頁
flash('余額更新成功!', 'success')
return redirect(url_for('get_user', user_id=user_id))
except ValueError:
# 變動值非數(shù)字時捕獲異常
flash('余額變動值必須為數(shù)字!', 'danger')
except Exception as e:
flash(f'余額更新失敗: {str(e)}', 'danger')
# GET請求:顯示余額修改表單(先查詢當(dāng)前用戶信息)
try:
query_sql = "select id, name, balance from t_user where id=%s;"
with get_conn() as conn, conn.cursor(cursor_factory=extras.DictCursor) as cur:
cur.execute(query_sql, (user_id,))
user = dict(cur.fetchone()) if cur.rowcount > 0 else None
if not user:
flash('該用戶不存在!', 'danger')
return redirect(url_for('index'))
# 渲染修改余額表單,傳遞當(dāng)前用戶信息
return render_template('update_balance.html', user=user)
except Exception as e:
flash(f'查詢用戶信息失敗: {str(e)}', 'danger')
return redirect(url_for('index'))
3.3.5 刪除用戶(刪)
通過/user/<user_id>/delete這個路由刪除指定用戶,為了防止誤刪,還得讓用戶確認(rèn)一下操作:
@app.route('/user/<int:user_id>/delete', methods=['POST'])
def delete_user(user_id):
"""刪除用戶(僅支持POST請求,避免GET請求誤觸發(fā))"""
try:
# 執(zhí)行刪除SQL
delete_sql = "delete from t_user where id=%s;"
with get_conn() as conn, conn.cursor() as cur:
cur.execute(delete_sql, (user_id,))
if cur.rowcount == 0:
flash('該用戶不存在!', 'danger')
else:
flash('用戶刪除成功!', 'success')
except Exception as e:
flash(f'用戶刪除失敗: {str(e)}', 'danger')
# 刪除后跳轉(zhuǎn)回首頁
return redirect(url_for('index'))
# --------------------------
# 啟動Flask服務(wù)
# --------------------------
if __name__ == '__main__':
# debug=True:開發(fā)模式(代碼修改后自動重啟,錯誤信息顯示在網(wǎng)頁上)
app.run(debug=True)
四、前端模板實(shí)現(xiàn)(templates文件夾)
前端咱們用“繼承式模板”來設(shè)計,base.html里定義公共的樣式和頁面結(jié)構(gòu),其他模板都繼承它,這樣能少寫很多重復(fù)代碼。
4.1 基礎(chǔ)模板(base.html)
所有頁面的公共部分,像頭部標(biāo)題、樣式、消息提示這些,都放在這個模板里:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kingbase用戶管理系統(tǒng)</title>
<!-- 公共CSS樣式(統(tǒng)一頁面風(fēng)格) -->
<style>
.container { max-width: 1200px; margin: 0 auto; padding: 20px; }
.flash { padding: 12px; margin: 15px 0; border-radius: 4px; font-size: 14px; }
.success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
.danger { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th, td { padding: 12px 15px; border: 1px solid #ddd; text-align: left; }
th { background-color: #f8f9fa; font-weight: bold; }
tr:hover { background-color: #f8f9fa; }
.btn { display: inline-block; padding: 8px 16px; margin: 0 5px; text-decoration: none;
color: #fff; border-radius: 4px; border: none; cursor: pointer; font-size: 14px; }
.btn-primary { background-color: #007bff; }
.btn-success { background-color: #28a745; }
.btn-danger { background-color: #dc3545; }
.form-group { margin-bottom: 20px; }
label { display: block; margin-bottom: 8px; font-weight: bold; }
input { padding: 10px; width: 350px; border: 1px solid #ddd; border-radius: 4px;
font-size: 14px; box-sizing: border-box; }
h1, h2 { color: #333; margin-bottom: 20px; }
.operate-btn-group { margin: 20px 0; }
</style>
</head>
<body>
<div class="container">
<!-- 頁面標(biāo)題(點(diǎn)擊可返回首頁) -->
<h1><a href="/" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" style="text-decoration: none; color: #333;">Kingbase用戶管理系統(tǒng)</a></h1>
<!-- 消息提示區(qū)域(顯示success/danger消息) -->
<div>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="flash {{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
<!-- 子模板內(nèi)容區(qū)域(由其他頁面填充) -->
{% block content %}{% endblock %}
</div>
</body>
</html>
4.2 首頁模板(index.html)
這個模板繼承base.html,主要用來展示用戶列表和操作按鈕:
{% extends "base.html" %} <!-- 繼承基礎(chǔ)模板 -->
{% block content %} <!-- 填充content區(qū)域 -->
<!-- 操作按鈕組(初始化表結(jié)構(gòu)、新增用戶) -->
<div class="operate-btn-group">
<a href="/init-schema" rel="external nofollow" class="btn btn-primary">初始化表結(jié)構(gòu)</a>
<a href="/user/create" rel="external nofollow" class="btn btn-success">添加新用戶</a>
</div>
<!-- 用戶列表標(biāo)題 -->
<h2>用戶列表</h2>
<!-- 若有用戶數(shù)據(jù),展示表格;否則提示無數(shù)據(jù) -->
{% if users %}
<table>
<tr>
<th>用戶ID</th>
<th>用戶名</th>
<th>賬戶余額(元)</th>
<th>創(chuàng)建時間</th>
<th>操作</th>
</tr>
{% for user in users %} <!-- 循環(huán)遍歷用戶列表 -->
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.balance }}</td>
<td>{{ user.created_at }}</td>
<td>
<!-- 查看詳情按鈕 -->
<a href="/user/{{ user.id }}" rel="external nofollow" rel="external nofollow" class="btn btn-primary">查看</a>
<!-- 調(diào)整余額按鈕 -->
<a href="/user/{{ user.id }}/balance" rel="external nofollow" rel="external nofollow" class="btn btn-success">調(diào)整余額</a>
<!-- 刪除按鈕(POST請求,需用表單包裹) -->
<form action="/user/{{ user.id }}/delete" method="post" style="display: inline;">
<button type="submit" class="btn btn-danger"
onclick="return confirm('確定要刪除該用戶嗎?刪除后不可恢復(fù)!')">
刪除
</button>
</form>
</td>
</tr>
{% endfor %}
</table>
{% else %}
<p style="color: #666; font-size: 16px;">暫無用戶數(shù)據(jù),請先初始化表結(jié)構(gòu)并添加用戶。</p>
{% endif %}
{% endblock %}

4.3 表結(jié)構(gòu)初始化模板(init_schema.html)
這個模板提供一個初始化表結(jié)構(gòu)的確認(rèn)按鈕,點(diǎn)擊就能觸發(fā)建表:
{% extends "base.html" %}
{% block content %}
<h2>初始化用戶表結(jié)構(gòu)</h2>
<p style="font-size: 16px; margin: 20px 0;">
點(diǎn)擊下方按鈕創(chuàng)建用戶表(t_user),若表已存在則不會重復(fù)創(chuàng)建。
</p>
<!-- 提交表單(POST請求觸發(fā)建表) -->
<form method="post">
<button type="submit" class="btn btn-success">確認(rèn)初始化表結(jié)構(gòu)</button>
<a href="/" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn btn-primary">返回首頁</a>
</form>
{% endblock %}

4.4 新增用戶模板(create_user.html)
這里有個表單,用戶可以輸入用戶名和初始余額,用來新增用戶:
{% extends "base.html" %}
{% block content %}
<h2>添加新用戶</h2>
<form method="post">
<!-- 用戶名輸入框(必填) -->
<div class="form-group">
<label for="name">用戶名 <span style="color: red;">*</span></label>
<input type="text" id="name" name="name" required
placeholder="請輸入用戶名(如:張三)">
</div>
<!-- 初始余額輸入框(可選) -->
<div class="form-group">
<label for="balance">初始余額(元)</label>
<input type="number" id="balance" name="balance" step="0.01" min="0"
placeholder="請輸入數(shù)字(默認(rèn)0,如:100.50)">
</div>
<!-- 提交與返回按鈕 -->
<button type="submit" class="btn btn-success">創(chuàng)建用戶</button>
<a href="/" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn btn-primary">返回首頁</a>
</form>
{% endblock %}

4.5 用戶詳情模板(user_detail.html)
這個模板用來展示單個用戶的詳細(xì)信息,看得更清楚:
{% extends "base.html" %}
{% block content %}
<h2>用戶詳情</h2>
{% if user %}
<table>
<tr>
<th style="width: 150px;">用戶ID</th>
<td>{{ user.id }}</td>
</tr>
<tr>
<th>用戶名</th>
<td>{{ user.name }}</td>
</tr>
<tr>
<th>賬戶余額(元)</th>
<td>{{ user.balance }}</td>
</tr>
<tr>
<th>創(chuàng)建時間</th>
<td>{{ user.created_at }}</td>
</tr>
</table>
<!-- 操作按鈕 -->
<div class="operate-btn-group">
<a href="/user/{{ user.id }}/balance" rel="external nofollow" rel="external nofollow" class="btn btn-success">調(diào)整余額</a>
<a href="/" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn btn-primary">返回用戶列表</a>
</div>
{% endif %}
{% endblock %}

4.6 余額修改模板(update_balance.html)
這里有個輸入框,用戶可以輸入余額變動值,用來調(diào)整用戶余額:
{% extends "base.html" %}
{% block content %}
<h2>調(diào)整用戶余額</h2>
{% if user %}
<!-- 顯示當(dāng)前用戶信息 -->
<p style="font-size: 16px; margin: 10px 0;">
當(dāng)前用戶:<strong>{{ user.name }}</strong>(ID:{{ user.id }})
</p>
<p style="font-size: 16px; margin: 10px 0;">
當(dāng)前余額:<strong>{{ user.balance }} 元</strong>
</p>
<!-- 余額變動表單 -->
<form method="post">
<div class="form-group">
<label for="delta">余額變動值(元)</label>
<input type="number" id="delta" name="delta" step="0.01" required
placeholder="正數(shù)增加,負(fù)數(shù)減少(如:50.00 或 -20.50)">
<small style="color: #666; display: block; margin-top: 5px;">
提示:輸入正數(shù)表示增加余額,輸入負(fù)數(shù)表示減少余額(如輸入-10表示減少10元)
</small>
</div>
<!-- 提交與返回按鈕 -->
<button type="submit" class="btn btn-success">確認(rèn)更新</button>
<a href="/user/{{ user.id }}" rel="external nofollow" rel="external nofollow" class="btn btn-primary">返回詳情</a>
</form>
{% endif %}
{% endblock %}

五、系統(tǒng)運(yùn)行與測試
代碼都寫完之后,咱們就可以啟動系統(tǒng),測試一下功能能不能正常用了。
5.1 啟動步驟
- 首先得確保KingbaseES數(shù)據(jù)庫已經(jīng)啟動了,而且DB_CFG里配置的IP、端口、賬號密碼都是對的。
- 找到項目根目錄(就是app.py所在的文件夾),打開命令行,輸入下面這個命令:
python app.py
- 看到下面這樣的輸出,就說明Flask服務(wù)啟動成功了:
* Serving Flask app 'app' * Debug mode: on WARNING: This is a development server. Do not use it in a production deployment. * Running on http://127.0.0.1:5000 Press CTRL+C to quit
5.2 功能測試流程
步驟1:初始化表結(jié)構(gòu)
- 打開瀏覽器,訪問
http://127.0.0.1:5000,點(diǎn)擊“初始化表結(jié)構(gòu)”按鈕,頁面會提示“表結(jié)構(gòu)初始化成功”。 - 這時候大家可以用KingbaseManager工具查一下,
TEST庫里已經(jīng)創(chuàng)建好t_user表了。
步驟2:新增用戶
- 點(diǎn)擊頁面上的“添加新用戶”,輸入用戶名(比如“張三”),再填個初始余額(比如“200”),然后點(diǎn)擊“創(chuàng)建用戶”,頁面會提示“用戶創(chuàng)建成功”。
- 回到首頁,就能看到剛才新增的用戶數(shù)據(jù)了。
步驟3:查看用戶詳情
- 找到剛才新增的用戶,點(diǎn)擊用戶那一行的“查看”按鈕,就能進(jìn)入詳情頁,用戶的ID、姓名、余額、創(chuàng)建時間都能看到。
步驟4:修改用戶余額
- 在詳情頁點(diǎn)擊“調(diào)整余額”,輸入變動值(比如“50”,意思是增加50元),然后點(diǎn)擊“確認(rèn)更新”,頁面會提示“余額更新成功”。
- 再回到詳情頁,就會發(fā)現(xiàn)余額已經(jīng)變成250元了。
步驟5:刪除用戶
- 回到首頁,找到要刪除的用戶,點(diǎn)擊“刪除”按鈕,會彈出一個確認(rèn)框,點(diǎn)擊“確定”,頁面提示“用戶刪除成功”。
- 這時候首頁就不會再顯示這個用戶的數(shù)據(jù)了。
六、常見問題與解決方案
開發(fā)和測試的時候,大家可能會遇到一些問題,我整理了幾個常見的,還給出了對應(yīng)的解決辦法:
6.1 數(shù)據(jù)庫連接失敗
- 錯誤提示:
數(shù)據(jù)庫連接失敗: could not connect to server: Connection refused - 原因:要么是KingbaseES數(shù)據(jù)庫沒啟動,要么是IP或者端口配置錯了。
- 解決方案:
- 先檢查KingbaseES服務(wù)有沒有啟動,可以通過服務(wù)管理器或者
sys_ctl命令來查看。 - 確認(rèn)一下
DB_CFG里的host(遠(yuǎn)程的話要填實(shí)際IP,本地就是127.0.0.1)和port(默認(rèn)是54321,有些環(huán)境可能是5432)對不對。 - 還要確保數(shù)據(jù)庫賬號密碼是對的,而且
system賬號有操作TEST庫的權(quán)限。
- 先檢查KingbaseES服務(wù)有沒有啟動,可以通過服務(wù)管理器或者
6.2 建表失敗
- 錯誤提示:
初始化失敗: permission denied for schema public - 原因:
system賬號對public模式?jīng)]有創(chuàng)建表的權(quán)限。 - 解決方案:
- 用KingbaseManager登錄
TEST庫,執(zhí)行下面這個授權(quán)SQL:
- 用KingbaseManager登錄
grant create on schema public to system;
執(zhí)行完之后,再重新做一次初始化操作就行。
6.3 余額修改時提示“非數(shù)字”
- 錯誤提示:
余額變動值必須為數(shù)字! - 原因:在輸入余額變動值的時候,里面混了非數(shù)字字符,比如字母、中文這些。
- 解決方案:輸入的時候注意一下,只填數(shù)字、小數(shù)點(diǎn)(比如“30.5”)或者負(fù)號(比如“-10”)就可以了。
七、項目擴(kuò)展建議
這個項目目前實(shí)現(xiàn)了基礎(chǔ)的用戶管理功能,大家可以根據(jù)自己的實(shí)際需求再擴(kuò)展一下,比如這些方向:
- 用戶認(rèn)證:加個登錄功能(可以用Flask-Login),這樣能防止沒授權(quán)的人隨便訪問系統(tǒng)。
- 分頁查詢:要是用戶數(shù)據(jù)特別多,在首頁加個分頁功能會更方便,用SQL的
limit和offset就能實(shí)現(xiàn)。 - 數(shù)據(jù)校驗(yàn):新增用戶的時候,加個用戶名唯一性校驗(yàn),先查一下數(shù)據(jù)庫里有沒有重名的,避免重復(fù)創(chuàng)建。
- 日志記錄:用
logging模塊記錄數(shù)據(jù)庫的操作日志,后面要是出了問題,排查起來會更方便。 - 生產(chǎn)環(huán)境部署:要是要放到生產(chǎn)環(huán)境用,記得把
debug模式關(guān)掉,用Gunicorn當(dāng)WSGI服務(wù)器,再配個Nginx做反向代理,這樣更穩(wěn)定。
八、總結(jié)
這篇文章從環(huán)境準(zhǔn)備、架構(gòu)設(shè)計、代碼實(shí)現(xiàn)到功能測試,把用Python操作KingbaseES數(shù)據(jù)庫,還有搭網(wǎng)頁管理系統(tǒng)的過程都講清楚了。咱們用Flask框架和psycopg2驅(qū)動,實(shí)現(xiàn)了數(shù)據(jù)增刪改查的全流程,前端用原生HTML/CSS,頁面簡單又好用。
希望這篇文章能幫大家快速掌握用Python操作國產(chǎn)數(shù)據(jù)庫的技巧,給國產(chǎn)化項目開發(fā)提供點(diǎn)參考。
以上就是Python操作國產(chǎn)金倉數(shù)據(jù)庫KingbaseES全流程的詳細(xì)內(nèi)容,更多關(guān)于Python操作數(shù)據(jù)庫KingbaseES的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python三元運(yùn)算符實(shí)現(xiàn)方法
這篇文章主要介紹了python實(shí)現(xiàn)三元運(yùn)算符的方法,大家參考使用吧2013-12-12
Python操作JSON實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)交換
這篇文章主要介紹了Python操作JSON實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)交換,JSON的全稱是 JavaScript Object Notation,是一種輕量級的數(shù)據(jù)交換格式,關(guān)于JSON的更多相關(guān)內(nèi)容感興趣的小伙伴可以參考一下2022-06-06
PyTorch函數(shù)torch.cat與torch.stac的區(qū)別小結(jié)
Pytorch中常用的兩個拼接函數(shù)torch.cat() 和 torch.stack(),本文主要介紹了這兩個函數(shù)的用法加區(qū)別,具有一定的參考價值,感興趣的可以了解一下2023-09-09
tensorflow轉(zhuǎn)換ckpt為savermodel模型的實(shí)現(xiàn)
這篇文章主要介紹了tensorflow轉(zhuǎn)換ckpt為savermodel模型的實(shí)現(xiàn),具有很好的參考價值,希望對大家有所幫助,一起跟隨小編過來看看吧2020-05-05
解決Alexnet訓(xùn)練模型在每個epoch中準(zhǔn)確率和loss都會一升一降問題
這篇文章主要介紹了解決Alexnet訓(xùn)練模型在每個epoch中準(zhǔn)確率和loss都會一升一降問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06
pip安裝提示Twisted錯誤問題(Python3.6.4安裝Twisted錯誤)
這篇文章主要介紹了pip安裝提示Twisted錯誤問題(Python3.6.4安裝Twisted錯誤),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05

