最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python操作國(guó)產(chǎn)金倉(cāng)數(shù)據(jù)庫(kù)KingbaseES全流程

 更新時(shí)間:2025年10月28日 08:51:55   作者:xcLeigh  
現(xiàn)在國(guó)產(chǎn)化替代是大趨勢(shì),國(guó)產(chǎn)數(shù)據(jù)庫(kù)的應(yīng)用越來(lái)越廣,金倉(cāng)數(shù)據(jù)庫(kù)(KingbaseES)作為其中的佼佼者,在政務(wù)、金融這些領(lǐng)域用得特別多,今天我就帶大家從0到1,一步步實(shí)現(xiàn)用Python操作KingbaseES數(shù)據(jù)庫(kù),需要的朋友可以參考下

前言

現(xiàn)在國(guó)產(chǎn)化替代是大趨勢(shì),國(guó)產(chǎn)數(shù)據(jù)庫(kù)的應(yīng)用范圍越來(lái)越廣,金倉(cāng)數(shù)據(jù)庫(kù)(KingbaseES)作為其中的佼佼者,在政務(wù)、金融等領(lǐng)域部署得特別多。今天我就帶大家從0到1,親手實(shí)現(xiàn)用Python操作KingbaseES數(shù)據(jù)庫(kù),還會(huì)基于Flask框架搭一個(gè)可視化的網(wǎng)頁(yè)管理系統(tǒng),數(shù)據(jù)的增刪改查(CRUD)全流程都能覆蓋到,Python開(kāi)發(fā)者和數(shù)據(jù)庫(kù)管理員跟著學(xué),都能掌握這套實(shí)用技能。

一、前置知識(shí)與環(huán)境準(zhǔn)備

開(kāi)始動(dòng)手前,咱們得把相關(guān)的環(huán)境和工具準(zhǔn)備好,這樣后面開(kāi)發(fā)的時(shí)候才不會(huì)卡殼。

1.1 核心技術(shù)棧

這次做項(xiàng)目用的技術(shù)都不復(fù)雜,也不用復(fù)雜的框架,輕量化還好上手,具體有這些:

  • 后端框架:Flask(這是個(gè)輕量級(jí)的Python Web框架,用來(lái)快速搭網(wǎng)頁(yè)服務(wù)特別方便)
  • 數(shù)據(jù)庫(kù)驅(qū)動(dòng):psycopg2(KingbaseES兼容PostgreSQL協(xié)議,直接用這個(gè)驅(qū)動(dòng)就能連接數(shù)據(jù)庫(kù))
  • 前端技術(shù):HTML + 原生CSS(不用額外學(xué)前端框架,咱們把核心功能實(shí)現(xiàn)了就行)
  • 數(shù)據(jù)庫(kù):KingbaseES V8/R3(我這次用的是比較常見(jiàn)的版本,其他版本操作步驟都一樣)

1.2 環(huán)境安裝步驟

步驟1:安裝Python(已經(jīng)裝了的話這步就跳過(guò))

直接去Python官網(wǎng)下載3.7及以上版本,安裝的時(shí)候記得勾選“Add Python to PATH”,這樣后面在命令行里就能直接調(diào)用pythonpip命令了。

步驟2:安裝依賴庫(kù)

打開(kāi)命令行,輸下面這些命令,就能把項(xiàng)目需要的依賴庫(kù)裝好:

# 安裝Flask框架
pip install flask
# 安裝KingbaseES數(shù)據(jù)庫(kù)驅(qū)動(dòng)(兼容PostgreSQL)
pip install psycopg2-binary

步驟3:確認(rèn)KingbaseES數(shù)據(jù)庫(kù)狀態(tài)

  • 首先得確保KingbaseES數(shù)據(jù)庫(kù)已經(jīng)啟動(dòng)了,而且能通過(guò)IP(比如本地的127.0.0.1)和端口(默認(rèn)常用端口是54321)訪問(wèn)到。
  • 提前創(chuàng)建好數(shù)據(jù)庫(kù),我這次用的是TEST庫(kù),大家可以用KingbaseES的圖形化工具KingbaseManager來(lái)創(chuàng)建。
  • 還要準(zhǔn)備好數(shù)據(jù)庫(kù)的賬號(hào)密碼,我這里用的是默認(rèn)管理員賬號(hào)system,密碼大家可以自己修改。

二、項(xiàng)目架構(gòu)設(shè)計(jì)

為了讓代碼結(jié)構(gòu)清晰,后面維護(hù)起來(lái)也方便,咱們采用“后端邏輯+前端模板”的分層設(shè)計(jì),整個(gè)項(xiàng)目的目錄結(jié)構(gòu)是這樣的:

kingbase_web_manager/  # 項(xiàng)目根目錄
├── app.py             # 后端核心邏輯(包含F(xiàn)lask服務(wù)、數(shù)據(jù)庫(kù)操作、路由定義)
└── templates/         # 前端HTML模板文件夾(用繼承式設(shè)計(jì),減少重復(fù)代碼)
    ├── base.html      # 基礎(chǔ)模板(放公共頭部、樣式、消息提示這些)
    ├── index.html     # 首頁(yè)(用來(lái)展示用戶列表)
    ├── init_schema.html  # 表結(jié)構(gòu)初始化頁(yè)面
    ├── create_user.html  # 新增用戶頁(yè)面
    ├── user_detail.html  # 用戶詳情頁(yè)面
    └── update_balance.html  # 余額修改頁(yè)面
  • 后端:通過(guò)Flask定義路由,處理前端發(fā)來(lái)的HTTP請(qǐng)求,再調(diào)用psycopg2去操作KingbaseES數(shù)據(jù)庫(kù)。
  • 前端:用HTML模板繼承的方式,base.html作為父模板,這樣所有頁(yè)面風(fēng)格能統(tǒng)一,也能少寫很多重復(fù)代碼。

三、后端核心實(shí)現(xiàn)(app.py)

后端就像是整個(gè)系統(tǒng)的“大腦”,負(fù)責(zé)連接數(shù)據(jù)庫(kù)、處理業(yè)務(wù)邏輯,最后把數(shù)據(jù)返回給前端。下面我分模塊給大家講核心代碼怎么寫。

3.1 初始化Flask與數(shù)據(jù)庫(kù)配置

首先創(chuàng)建app.py文件,先把Flask應(yīng)用初始化好,再配置KingbaseES數(shù)據(jù)庫(kù)的連接參數(shù):

from flask import Flask, jsonify, request, render_template, redirect, url_for, flash
import psycopg2  # KingbaseES數(shù)據(jù)庫(kù)驅(qū)動(dòng)
import psycopg2.extras as extras  # 擴(kuò)展功能(如DictCursor,讓查詢結(jié)果為字典格式)

# 初始化Flask應(yīng)用
app = Flask(__name__)
# 配置secret_key(用于flash消息提示,防止跨站請(qǐng)求偽造)
app.secret_key = 'kingbase_web_manager_2024'

# --------------------------
# KingbaseES數(shù)據(jù)庫(kù)連接配置
# --------------------------
DB_CFG = dict(
    host="127.0.0.1",    # 數(shù)據(jù)庫(kù)IP(本地為127.0.0.1,遠(yuǎn)程需填實(shí)際IP)
    port=54321,          # KingbaseES默認(rèn)常見(jiàn)端口(不同環(huán)境可能為5432,需確認(rèn))
    dbname="TEST",       # 數(shù)據(jù)庫(kù)名稱(提前創(chuàng)建好)
    user="system",       # 數(shù)據(jù)庫(kù)賬號(hào)(管理員賬號(hào))
    password="jcsjk520.",# 數(shù)據(jù)庫(kù)密碼(替換為你的實(shí)際密碼)
    connect_timeout=5,   # 連接超時(shí)時(shí)間(5秒)
)

# --------------------------
# 數(shù)據(jù)庫(kù)連接工具函數(shù)
# --------------------------
def get_conn():
    """獲取KingbaseES數(shù)據(jù)庫(kù)連接"""
    try:
        # 使用psycopg2.connect連接數(shù)據(jù)庫(kù),**DB_CFG表示解包配置字典
        conn = psycopg2.connect(**DB_CFG)
        return conn
    except Exception as e:
        # 連接失敗時(shí)拋出異常(后續(xù)路由會(huì)捕獲處理)
        raise Exception(f"數(shù)據(jù)庫(kù)連接失敗: {str(e)}")

3.2 表結(jié)構(gòu)初始化(建表)

第一次用的時(shí)候,得先創(chuàng)建用戶表(t_user),咱們可以通過(guò)/init-schema這個(gè)路由,在網(wǎng)頁(yè)端觸發(fā)建表操作:

@app.route('/init-schema', methods=['GET', 'POST'])
def init_schema():
    """初始化用戶表結(jié)構(gòu)(GET請(qǐng)求顯示頁(yè)面,POST請(qǐng)求執(zhí)行建表)"""
    # 1. POST請(qǐng)求:用戶點(diǎn)擊"初始化"按鈕,執(zhí)行建表SQL
    if request.method == 'POST':
        # 定義建表SQL(if not exists確保表不存在時(shí)才創(chuàng)建,避免重復(fù)執(zhí)行報(bào)錯(cuò))
        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)建時(shí)間(默認(rèn)當(dāng)前時(shí)間)
        );
        """
        try:
            # 使用with語(yǔ)句自動(dòng)管理連接和游標(biāo)(無(wú)需手動(dòng)關(guān)閉)
            with get_conn() as conn, conn.cursor() as cur:
                cur.execute(create_table_sql)  # 執(zhí)行建表SQL
            # 建表成功,通過(guò)flash傳遞成功消息(前端會(huì)顯示)
            flash('表結(jié)構(gòu)初始化成功!', 'success')
        except Exception as e:
            # 建表失敗,傳遞錯(cuò)誤消息
            flash(f'初始化失敗: {str(e)}', 'danger')
        # 無(wú)論成功與否,跳轉(zhuǎn)回首頁(yè)
        return redirect(url_for('index'))
    
    # 2. GET請(qǐng)求:顯示初始化表結(jié)構(gòu)的頁(yè)面
    return render_template('init_schema.html')

3.3 用戶數(shù)據(jù)增刪改查實(shí)現(xiàn)

接下來(lái)咱們實(shí)現(xiàn)核心的CRUD功能,每個(gè)功能對(duì)應(yīng)一個(gè)路由,專門處理前端的請(qǐng)求,然后操作數(shù)據(jù)庫(kù)。

3.3.1 首頁(yè):展示所有用戶(查-列表)

首頁(yè)/這個(gè)路由會(huì)查詢t_user表里的所有數(shù)據(jù),然后把數(shù)據(jù)傳給前端模板展示出來(lái):

@app.route('/')
def index():
    """首頁(yè):展示所有用戶列表"""
    try:
        # 查詢所有用戶數(shù)據(jù)(按ID升序,可選)
        query_sql = "select id, name, balance, created_at from t_user order by id;"
        # 使用DictCursor,讓查詢結(jié)果為字典(便于前端通過(guò)鍵名獲取值)
        with get_conn() as conn, conn.cursor(cursor_factory=extras.DictCursor) as cur:
            cur.execute(query_sql)
            # fetchall()獲取所有結(jié)果,轉(zhuǎn)換為列表(每個(gè)元素是字典)
            users = [dict(row) for row in cur.fetchall()]
        # 渲染首頁(yè)模板,傳遞用戶列表數(shù)據(jù)
        return render_template('index.html', users=users)
    except Exception as e:
        # 查詢失敗,顯示錯(cuò)誤消息,傳遞空列表
        flash(f'數(shù)據(jù)庫(kù)查詢錯(cuò)誤: {str(e)}', 'danger')
        return render_template('index.html', users=[])

3.3.2 新增用戶(增)

通過(guò)/user/create這個(gè)路由實(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)失敗,返回表單頁(yè)面
        
        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)回首頁(yè)
            flash(f'用戶創(chuàng)建成功!用戶ID: {user_id}', 'success')
            return redirect(url_for('index'))
        except ValueError:
            # 余額非數(shù)字時(shí)捕獲異常
            flash('初始余額必須為數(shù)字!', 'danger')
        except Exception as e:
            # 其他錯(cuò)誤(如數(shù)據(jù)庫(kù)異常)
            flash(f'用戶創(chuàng)建失敗: {str(e)}', 'danger')
    
    # GET請(qǐng)求:顯示新增用戶表單
    return render_template('create_user.html')

3.3.3 查看用戶詳情(查-單條)

通過(guò)用戶ID查詢單條用戶數(shù)據(jù),然后展示詳細(xì)信息:

@app.route('/user/<int:user_id>')
def get_user(user_id):
    """查看單個(gè)用戶詳情(通過(guò)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)回首頁(yè)
        
        # 渲染詳情頁(yè)面,傳遞用戶數(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 修改用戶余額(改)

通過(guò)/user/<user_id>/balance這個(gè)路由調(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. 獲取余額變動(dòng)值(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表示無(wú)此用戶)
                if cur.rowcount == 0:
                    flash('該用戶不存在!', 'danger')
                    return redirect(url_for('index'))
            
            # 3. 更新成功,跳轉(zhuǎn)回用戶詳情頁(yè)
            flash('余額更新成功!', 'success')
            return redirect(url_for('get_user', user_id=user_id))
        except ValueError:
            # 變動(dòng)值非數(shù)字時(shí)捕獲異常
            flash('余額變動(dòng)值必須為數(shù)字!', 'danger')
        except Exception as e:
            flash(f'余額更新失敗: {str(e)}', 'danger')
    
    # GET請(qǐng)求:顯示余額修改表單(先查詢當(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 刪除用戶(刪)

通過(guò)/user/<user_id>/delete這個(gè)路由刪除指定用戶,為了防止誤刪,還得讓用戶確認(rèn)一下操作:

@app.route('/user/<int:user_id>/delete', methods=['POST'])
def delete_user(user_id):
    """刪除用戶(僅支持POST請(qǐng)求,避免GET請(qǐng)求誤觸發(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)回首頁(yè)
    return redirect(url_for('index'))

# --------------------------
# 啟動(dòng)Flask服務(wù)
# --------------------------
if __name__ == '__main__':
    # debug=True:開(kāi)發(fā)模式(代碼修改后自動(dòng)重啟,錯(cuò)誤信息顯示在網(wǎng)頁(yè)上)
    app.run(debug=True)

四、前端模板實(shí)現(xiàn)(templates文件夾)

前端咱們用“繼承式模板”來(lái)設(shè)計(jì),base.html里定義公共的樣式和頁(yè)面結(jié)構(gòu),其他模板都繼承它,這樣能少寫很多重復(fù)代碼。

4.1 基礎(chǔ)模板(base.html)

所有頁(yè)面的公共部分,像頭部標(biāo)題、樣式、消息提示這些,都放在這個(gè)模板里:

<!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)一頁(yè)面風(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">
        <!-- 頁(yè)面標(biāo)題(點(diǎn)擊可返回首頁(yè)) -->
        <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ū)域(由其他頁(yè)面填充) -->
        {% block content %}{% endblock %}
    </div>
</body>
</html>

4.2 首頁(yè)模板(index.html)

這個(gè)模板繼承base.html,主要用來(lái)展示用戶列表和操作按鈕:

{% 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ù),展示表格;否則提示無(wú)數(shù)據(jù) -->
    {% if users %}
        <table>
            <tr>
                <th>用戶ID</th>
                <th>用戶名</th>
                <th>賬戶余額(元)</th>
                <th>創(chuàng)建時(shí)間</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請(qǐng)求,需用表單包裹) -->
                    <form action="/user/{{ user.id }}/delete" method="post" style="display: inline;">
                        <button type="submit" class="btn btn-danger" 
                                onclick="return confirm('確定要?jiǎng)h除該用戶嗎?刪除后不可恢復(fù)!')">
                            刪除
                        </button>
                    </form>
                </td>
            </tr>
            {% endfor %}
        </table>
    {% else %}
        <p style="color: #666; font-size: 16px;">暫無(wú)用戶數(shù)據(jù),請(qǐng)先初始化表結(jié)構(gòu)并添加用戶。</p>
    {% endif %}
{% endblock %}

4.3 表結(jié)構(gòu)初始化模板(init_schema.html)

這個(gè)模板提供一個(gè)初始化表結(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),若表已存在則不會(huì)重復(fù)創(chuàng)建。
    </p>
    <!-- 提交表單(POST請(qǐng)求觸發(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">返回首頁(yè)</a>
    </form>
{% endblock %}

4.4 新增用戶模板(create_user.html)

這里有個(gè)表單,用戶可以輸入用戶名和初始余額,用來(lái)新增用戶:

{% 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="請(qǐng)輸入用戶名(如:張三)">
        </div>
        <!-- 初始余額輸入框(可選) -->
        <div class="form-group">
            <label for="balance">初始余額(元)</label>
            <input type="number" id="balance" name="balance" step="0.01" min="0"
                   placeholder="請(qǐng)輸入數(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">返回首頁(yè)</a>
    </form>
{% endblock %}

4.5 用戶詳情模板(user_detail.html)

這個(gè)模板用來(lái)展示單個(gè)用戶的詳細(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)建時(shí)間</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)

這里有個(gè)輸入框,用戶可以輸入余額變動(dòng)值,用來(lái)調(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>
        
        <!-- 余額變動(dòng)表單 -->
        <form method="post">
            <div class="form-group">
                <label for="delta">余額變動(dòng)值(元)</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)行與測(cè)試

代碼都寫完之后,咱們就可以啟動(dòng)系統(tǒng),測(cè)試一下功能能不能正常用了。

5.1 啟動(dòng)步驟

  • 首先得確保KingbaseES數(shù)據(jù)庫(kù)已經(jīng)啟動(dòng)了,而且DB_CFG里配置的IP、端口、賬號(hào)密碼都是對(duì)的。
  • 找到項(xiàng)目根目錄(就是app.py所在的文件夾),打開(kāi)命令行,輸入下面這個(gè)命令:
python app.py
  • 看到下面這樣的輸出,就說(shuō)明Flask服務(wù)啟動(dòng)成功了:
* 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 功能測(cè)試流程

步驟1:初始化表結(jié)構(gòu)

  • 打開(kāi)瀏覽器,訪問(wèn)http://127.0.0.1:5000,點(diǎn)擊“初始化表結(jié)構(gòu)”按鈕,頁(yè)面會(huì)提示“表結(jié)構(gòu)初始化成功”。
  • 這時(shí)候大家可以用KingbaseManager工具查一下,TEST庫(kù)里已經(jīng)創(chuàng)建好t_user表了。

步驟2:新增用戶

  • 點(diǎn)擊頁(yè)面上的“添加新用戶”,輸入用戶名(比如“張三”),再填個(gè)初始余額(比如“200”),然后點(diǎn)擊“創(chuàng)建用戶”,頁(yè)面會(huì)提示“用戶創(chuàng)建成功”。
  • 回到首頁(yè),就能看到剛才新增的用戶數(shù)據(jù)了。

步驟3:查看用戶詳情

  • 找到剛才新增的用戶,點(diǎn)擊用戶那一行的“查看”按鈕,就能進(jìn)入詳情頁(yè),用戶的ID、姓名、余額、創(chuàng)建時(shí)間都能看到。

步驟4:修改用戶余額

  • 在詳情頁(yè)點(diǎn)擊“調(diào)整余額”,輸入變動(dòng)值(比如“50”,意思是增加50元),然后點(diǎn)擊“確認(rèn)更新”,頁(yè)面會(huì)提示“余額更新成功”。
  • 再回到詳情頁(yè),就會(huì)發(fā)現(xiàn)余額已經(jīng)變成250元了。

步驟5:刪除用戶

  • 回到首頁(yè),找到要?jiǎng)h除的用戶,點(diǎn)擊“刪除”按鈕,會(huì)彈出一個(gè)確認(rèn)框,點(diǎn)擊“確定”,頁(yè)面提示“用戶刪除成功”。
  • 這時(shí)候首頁(yè)就不會(huì)再顯示這個(gè)用戶的數(shù)據(jù)了。

六、常見(jiàn)問(wèn)題與解決方案

開(kāi)發(fā)和測(cè)試的時(shí)候,大家可能會(huì)遇到一些問(wèn)題,我整理了幾個(gè)常見(jiàn)的,還給出了對(duì)應(yīng)的解決辦法:

6.1 數(shù)據(jù)庫(kù)連接失敗

  • 錯(cuò)誤提示數(shù)據(jù)庫(kù)連接失敗: could not connect to server: Connection refused
  • 原因:要么是KingbaseES數(shù)據(jù)庫(kù)沒(méi)啟動(dòng),要么是IP或者端口配置錯(cuò)了。
  • 解決方案
    1. 先檢查KingbaseES服務(wù)有沒(méi)有啟動(dòng),可以通過(guò)服務(wù)管理器或者sys_ctl命令來(lái)查看。
    2. 確認(rèn)一下DB_CFG里的host(遠(yuǎn)程的話要填實(shí)際IP,本地就是127.0.0.1)和port(默認(rèn)是54321,有些環(huán)境可能是5432)對(duì)不對(duì)。
    3. 還要確保數(shù)據(jù)庫(kù)賬號(hào)密碼是對(duì)的,而且system賬號(hào)有操作TEST庫(kù)的權(quán)限。

6.2 建表失敗

  • 錯(cuò)誤提示初始化失敗: permission denied for schema public
  • 原因system賬號(hào)對(duì)public模式?jīng)]有創(chuàng)建表的權(quán)限。
  • 解決方案
    1. 用KingbaseManager登錄TEST庫(kù),執(zhí)行下面這個(gè)授權(quán)SQL:
grant create on schema public to system;

執(zhí)行完之后,再重新做一次初始化操作就行。

6.3 余額修改時(shí)提示“非數(shù)字”

  • 錯(cuò)誤提示余額變動(dòng)值必須為數(shù)字!
  • 原因:在輸入余額變動(dòng)值的時(shí)候,里面混了非數(shù)字字符,比如字母、中文這些。
  • 解決方案:輸入的時(shí)候注意一下,只填數(shù)字、小數(shù)點(diǎn)(比如“30.5”)或者負(fù)號(hào)(比如“-10”)就可以了。

七、項(xiàng)目擴(kuò)展建議

這個(gè)項(xiàng)目目前實(shí)現(xiàn)了基礎(chǔ)的用戶管理功能,大家可以根據(jù)自己的實(shí)際需求再擴(kuò)展一下,比如這些方向:

  1. 用戶認(rèn)證:加個(gè)登錄功能(可以用Flask-Login),這樣能防止沒(méi)授權(quán)的人隨便訪問(wèn)系統(tǒng)。
  2. 分頁(yè)查詢:要是用戶數(shù)據(jù)特別多,在首頁(yè)加個(gè)分頁(yè)功能會(huì)更方便,用SQL的limitoffset就能實(shí)現(xiàn)。
  3. 數(shù)據(jù)校驗(yàn):新增用戶的時(shí)候,加個(gè)用戶名唯一性校驗(yàn),先查一下數(shù)據(jù)庫(kù)里有沒(méi)有重名的,避免重復(fù)創(chuàng)建。
  4. 日志記錄:用logging模塊記錄數(shù)據(jù)庫(kù)的操作日志,后面要是出了問(wèn)題,排查起來(lái)會(huì)更方便。
  5. 生產(chǎn)環(huán)境部署:要是要放到生產(chǎn)環(huán)境用,記得把debug模式關(guān)掉,用Gunicorn當(dāng)WSGI服務(wù)器,再配個(gè)Nginx做反向代理,這樣更穩(wěn)定。

八、總結(jié)

這篇文章從環(huán)境準(zhǔn)備、架構(gòu)設(shè)計(jì)、代碼實(shí)現(xiàn)到功能測(cè)試,把用Python操作KingbaseES數(shù)據(jù)庫(kù),還有搭網(wǎng)頁(yè)管理系統(tǒng)的過(guò)程都講清楚了。咱們用Flask框架和psycopg2驅(qū)動(dòng),實(shí)現(xiàn)了數(shù)據(jù)增刪改查的全流程,前端用原生HTML/CSS,頁(yè)面簡(jiǎn)單又好用。

希望這篇文章能幫大家快速掌握用Python操作國(guó)產(chǎn)數(shù)據(jù)庫(kù)的技巧,給國(guó)產(chǎn)化項(xiàng)目開(kāi)發(fā)提供點(diǎn)參考。

以上就是Python操作國(guó)產(chǎn)金倉(cāng)數(shù)據(jù)庫(kù)KingbaseES全流程的詳細(xì)內(nèi)容,更多關(guān)于Python操作數(shù)據(jù)庫(kù)KingbaseES的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

九龙坡区| 花莲市| 沽源县| 萍乡市| 景谷| 陕西省| 长葛市| 自贡市| 威远县| 上饶市| 康保县| 莱芜市| 唐海县| 乌兰浩特市| 柘荣县| 泰安市| 延庆县| 大洼县| 山丹县| 从江县| 梁山县| 凉城县| 集贤县| 锦屏县| 丰台区| 安国市| 保德县| 敦煌市| 巨野县| 当涂县| 盐源县| 青海省| 久治县| 克东县| 石门县| 温泉县| 吐鲁番市| 鄂托克旗| 新干县| 南召县| 景德镇市|