途知旅行助手云平台部署与数据库的建立
我们使用了华为云虚拟ecs,则需要先打开修改安全组配置规则

添加入方向规则

然后正式开始,打开你的shell软件(或者华为云的cloudshell),登录创建链接

1.切换到omm用户,以操作系统用户omm登录数据库主节点。
su - omm
使用gsql工具登陆数据库。
gsql -d postgres -p 26000 -r
创建数据库lkun。
CREATE DATABASE lkun ENCODING 'UTF8' TEMPLATE template0;
连接finance数据库。
\connect lkun
创建名为lkun的schema,并设置lkun为当前的schema。
CREATE SCHEMA lkun;
将默认搜索路径设为lkun。
SET search_path TO lkun;
删除表client
DROP TABLE IF EXISTS client;
2.关闭前面的窗口,新建一个shell窗口,在GS_HOME中查找pg_hba.conf文件,华为云默认的在/gaussdb/data/db1里面
cd /gaussdb/data/db1
vim pg_hba.conf
在里面找到ipv4的地方,添加这行
host all all 0.0.0.0/0 md5

Esc之后:wq退出,之后进入omm保存
su - omm
gs_ctl reload -D /gaussdb/data/db1/

3.修改数据库监听地址。
在GS_HOME中,华为云数据库GS_HOME默认设置也在/gaussdb/data/db1,打开postgresql.conf
cd /gaussdb/data/db1
vim postgresql.conf
将listen_addresses的值修改成为*。
listen_addresses = '*'

接着,取消掉password_encryption_type的注释,修改:
password_encryption_type = 1

修改完成后esc,:wq退出,重启数据库生效(-D后面的数据库默认路径,需要根据实际情况进行修改)。
gs_ctl restart -D /gaussdb/data/db1/
4.使用omm用户登陆数据库给dbuser用户授权
su - omm
gsql -d postgres -p 26000 -r
创建用户,此处名字取lk,密码取cqq_lk123:
create user lk identified by 'cqq_lk123';
alter user lk sysadmin;

这样就完成了数据库的搭建,接着,我进行了六个表的创建:
- Users (用户表)
CREATE TABLE Users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
role VARCHAR(20) DEFAULT 'user'::character varying
);
创建结果:

2.城市表 (Cities)
CREATE TABLE Cities (
city_id SERIAL PRIMARY KEY,
city_name VARCHAR(100) NOT NULL,
province VARCHAR(100)
);
结果:

3.景点表 (Attractions)
CREATE TABLE Attractions (
attraction_id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
address VARCHAR(255),
ticket_price DECIMAL(10, 2),
city_id INTEGER REFERENCES Cities(city_id) ON DELETE SET NULL,
user_id INTEGER REFERENCES Users(user_id) ON DELETE SET NULL,
open_time TIME WITHOUT TIME ZONE,
close_time TIME WITHOUT TIME ZONE,
rating NUMERIC(2, 1) DEFAULT 5.0,
category VARCHAR(50) CHECK (category IN ('自然风光', '历史古迹', '文化艺术', '主题乐园', '城市地标', '其他')),
image_urls TEXT[],
longitude DECIMAL(9, 6),
latitude DECIMAL(9, 6)
);
结果:

4.评论表 (Reviews)
CREATE TABLE Reviews (
review_id SERIAL PRIMARY KEY,
rating SMALLINT CHECK (rating >= 1 AND rating <= 5),
comment_text TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
user_id INTEGER REFERENCES Users(user_id) ON DELETE CASCADE,
attraction_id INTEGER REFERENCES Attractions(attraction_id) ON DELETE CASCADE,
image_urls TEXT[]
);
结果:

5.行程表 (Itineraries)
CREATE TABLE Itineraries (
itinerary_id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
start_date DATE,
end_date DATE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
user_id INTEGER REFERENCES Users(user_id) ON DELETE CASCADE
);
结果:

6.行程景点关联表 (Itinerary_Attractions)
CREATE TABLE Itinerary_Attractions (
itinerary_id INTEGER REFERENCES Itineraries(itinerary_id) ON DELETE CASCADE,
attraction_id INTEGER REFERENCES Attractions(attraction_id) ON DELETE CASCADE,
visit_day INTEGER,
visit_time TIME WITHOUT TIME ZONE,
notes TEXT,
PRIMARY KEY (itinerary_id, attraction_id)
);
结果:

至此,完成了数据库的搭建以及表的建立
管理系统::本人参与了管理系统的开发,该系统旨在为用户提供景点浏览、行程规划以及评论互动等功能,同时也为管理员提供了强大的后台管理能力。
一、 后端实现:Flask + PostgreSQL
后端我选择了 Python Flask 框架,因为它轻量、灵活且易于扩展。数据库方面使用了openguass,通过 psycopg2 驱动进行连接。
- 核心架构与数据库连接
系统采用经典的 MVC 模式(在 Flask 中通常是 MVT)。我封装了一个 get_db_connection 函数来管理数据库连接,确保每次请求都能安全地获取和释放资源。
关键代码 (app.py):
import psycopg2
from flask import Flask, render_template, request, session
from flask_bcrypt import Bcrypt
app = Flask(__name__)
bcrypt = Bcrypt(app) # 用于密码加密
# 数据库配置
DB_CONFIG = {
'host': '1.92.112.241',
'port': '26000',
'dbname': 'travel_db',
'user': 'my_root',
'password': '...'
}
def get_db_connection():
"""建立数据库连接"""
try:
conn = psycopg2.connect(**DB_CONFIG)
return conn
except Exception as e:
print(f"数据库连接失败: {e}")
return None
- 权限管理与路由逻辑
为了区分普通用户和管理员,我利用 Flask 的 session 存储用户状态,并编写了辅助函数 is_admin() 进行权限校验。
例如,在编辑景点的路由中,我加入了严格的权限判断:只有“作者本人”或“管理员”才能修改信息。
关键代码 (权限控制):
# 辅助函数:检查权限
def is_admin():
return session.get('role') in ['admin', 'super_admin']
# 路由示例:编辑景点
@app.route('/edit/<int:id>', methods=('GET', 'POST'))
def edit_attraction(id):
if not is_logged_in():
return redirect(url_for('login'))
# ... (省略数据库查询代码) ...
# 权限校验:必须是作者本人或者管理员
if attraction_author_id[0] != session['user_id'] and not is_admin():
flash('您无权编辑此景点。', 'danger')
return redirect(url_for('attraction_detail', id=id))
# ... (后续更新逻辑)
二、 前端实现:Jinja2 + Bootstrap 5
前端部分,我使用了 Flask 自带的 Jinja2 模板引擎进行服务端渲染,并结合 Bootstrap 5 快速构建响应式 UI。
- 模板继承 (Base Template)
为了保持页面风格统一并减少重复代码,我定义了一个 base.html 作为父模板。它包含了导航栏、页脚以及全局的 CSS/JS 引用。其他页面只需继承它并填充 {% block content %} 即可。
关键代码 (templates/base.html):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{% block title %}途知·旅游助手{% endblock %}</title>
<!-- 引入 Bootstrap 5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!-- 导航栏组件 -->
{% include '_nav.html' %}
<!-- 消息闪现区域 -->
<div class="container mt-3">
{% include '_messages.html' %}
</div>
<!-- 页面主要内容 -->
<div class="main-content">
{% block content %}{% endblock %}
</div>
<footer>...</footer>
</body>
</html>
- 数据展示与交互
在景点列表页 (attractions.html),我利用 Jinja2 的循环结构 {% for %} 动态渲染数据库返回的数据。同时,利用 Bootstrap 的 Grid 系统实现了卡片式布局,让界面看起来整洁美观。
关键代码 (templates/attractions.html):
{% extends 'base.html' %}
{% block content %}
<div class="container mt-4">
<!-- 搜索与筛选区 -->
<form action="/attractions" method="GET" class="row g-3">
<!-- ... 省略搜索框代码 ... -->
</form>
<!-- 景点列表循环 -->
<div class="row row-cols-1 row-cols-md-3 g-4">
{% for attraction in attractions %}
<div class="col">
<div class="card h-100 shadow-sm">
<!-- 景点图片 -->
<img src="{{ attraction[4][0] if attraction[4] else '...' }}" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">{{ attraction[1] }}</h5>
<p class="card-text text-truncate">{{ attraction[2] }}</p>
<div class="d-flex justify-content-between align-items-center">
<span class="text-danger fw-bold">¥{{ attraction[3] }}</span>
<a href="/attraction/{{ attraction[0] }}" class="btn btn-sm btn-outline-primary">查看详情</a>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
通过 Flask 强大的路由处理能力和 Jinja2 的模板渲染,配合 PostgreSQL 数据库,我成功构建了一个逻辑清晰、功能完备的旅游管理系统。这种前后端不分离的开发模式(服务端渲染)在开发中小型应用时,依然具有开发速度快、SEO 友好等优势。
管理系统前后端:https://gitee.com/changqianqi/2025_crawl-project/tree/master/manage
浙公网安备 33010602011771号