途知旅行助手云平台部署与数据库的建立


我们使用了华为云虚拟ecs,则需要先打开修改安全组配置规则
​​image
​​
添加入方向规则
image

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

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
image

Esc之后:wq退出,之后进入omm保存

su - omm

gs_ctl reload -D /gaussdb/data/db1/
image

3.修改数据库监听地址。

在GS_HOME中,华为云数据库GS_HOME默认设置也在/gaussdb/data/db1,打开postgresql.conf

cd /gaussdb/data/db1

vim postgresql.conf

将listen_addresses的值修改成为*。

listen_addresses = '*'
image

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

password_encryption_type = 1

image

修改完成后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;
image

这样就完成了数据库的搭建,接着,我进行了六个表的创建:

  1. 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
);

创建结果:
image

2.城市表 (Cities)

CREATE TABLE Cities (
    city_id SERIAL PRIMARY KEY,
    city_name VARCHAR(100) NOT NULL,
    province VARCHAR(100)
);

结果:
image

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)
);

结果:
image

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[]
);

结果:
image

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
);

结果:
image

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)
);

结果:
image

至此,完成了数据库的搭建以及表的建立

管理系统::本人参与了管理系统的开发,该系统旨在为用户提供景点浏览、行程规划以及评论互动等功能,同时也为管理员提供了强大的后台管理能力。

一、 后端实现:Flask + PostgreSQL
后端我选择了 Python Flask 框架,因为它轻量、灵活且易于扩展。数据库方面使用了openguass,通过 psycopg2 驱动进行连接。

  1. 核心架构与数据库连接
    系统采用经典的 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
  1. 权限管理与路由逻辑
    为了区分普通用户和管理员,我利用 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。

  1. 模板继承 (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>
  1. 数据展示与交互
    在景点列表页 (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

posted @ 2025-12-20 00:28  changqianqi  阅读(8)  评论(0)    收藏  举报