1.7 Web学生管理系统

news2024/10/2 10:35:56

1.定义通讯协议


基于前面介绍过的 FLask Web 网站urlib 的访问网站的方法,设计一个综合应用实例。它是一个基于 Web 的学生记录管理程序。

学生的记录包括 id(学号) 、 name(姓名) 、 grade(成绩), 服务器的作用是建立与维护一个Sqllite 的学生数据库 student.db 中的学生记录表 student。

服务器建立一个 Web 网站, 同时提供查询学生记录、增加学生记录、删除学生记录等接口服务。服务器为了与客户端通信,建立一个opt 的参数如下表:

opt值

含 义

init

初始化学生表

insert

增加学生

delete

删除学生

update

更改学生

select

查询学生

opt 参数值

获取学生记录

规定如下:
  • 如果客户端向服务器发送 opt="init" ,那么服务器创建 students 表,并返回是否创建成功,如果成功就返回 {"msg":"OK"}

  • 如果客户端向服务器发送 opt="insert" , 同时发送id , name , grade 参数,那么服务器向数据库表插入一条学生记录,并返回是否插入成功信息,如果成功就返回 {"msg":"OK"}

  • 如果客户端向服务器发送 opt="delete" , 同时发送 id 参数,那么服务器从数据库表中删除学号为 id 的一条学生记录,并返回是否删除成功的信息,如果删除成功就返回 {"msg":"OK"}

  • 如果客户端向服务器发送 opt="update" , 同时发送 id 参数,那么服务器从数据库表中更改学号为 id 的一条学生记录,并返回是否更改成功的信息,如果更改成功就返回 {"msg":"OK"}

  • 如果客户端向服务器发送 opt="select" , 同时发送id 参数,那么服务器从数据库表中查询学号为 id 的一条学生记录,并返回是否查询成功的信息,如果查询成功就返回 {"msg":"OK"}

  • 如果客户端不向服务器发送 opt 参数值,那么服务器获取所有的学生记录返回给客户端,如果成功就返回 {"msg":"OK","data":"rows"} , 其中 rows 是学生的记录行的列表。

2.服务器程序


服务器程序server.py如下:

import flask
import sqlite3
import json

# 初始化一个Flask对象,参数__name__是程序的名称
app = flask.Flask(__name__)


class StudentDB:
    def __init__(self):
        self.cursor = None
        self.con = None

    # 通过学生类打开一个数据库,采用sqlite3.connect来连接
    def openDB(self):
        self.con = sqlite3.connect("students.db")
        # 获取Cursor游标对象,用于执行sql语句并获得结果
        self.cursor = self.con.cursor()

    # 关闭连接
    def closeDB(self):
        self.con.commit()
        self.con.close()

    # 创建一个学生表
    def initTable(self):
        res = {}
        try:
            self.cursor.execute("create table students (id varchar(16) "
                                "primary key,name varchar(16),grade int)")
            res["msg"] = "OK"
        except Exception as err:
            res["msg"] = str(err)
        return res

    # 插入学生
    def insertRow(self, id, name, grade):
        res = {}
        try:
            self.cursor.execute("insert into students (id,name,grade) "
                                "values(?,?,?)", (id, name, grade))
            res["msg"] = "OK"
        except Exception as err:
            res["msg"] = str(err)
        return res

    # 删除学生
    def deleteRow(self, id):
        res = {}
        try:
            self.cursor.execute("delete from students where id=?", (id,))
            res["msg"] = "OK"
        except Exception as err:
            res["msg"] = str(err)
        return res

    # 修改学生
    def updateRow(self, id):
        res = {}
        try:
            self.cursor.execute("update students set name=?,grade=? where id=?", (id,))
            res["smg"] = "OK"
        except Exception as err:
            res["msg"] = str(err)
        return res

    # 获取学生的所有信息
    def selectRows(self):
        res = {}
        try:
            data = []
            self.cursor.execute("select * from students order by id")
            rows = self.cursor.fetchall()  # 在 Python 中使用 fetchall() 从数据库文件中提取元素
            for row in rows:
                # 每一个学生记录都是一个字典
                d = {"id": row[0], "name": row[1], "grade": row[2]}
                data.append(d)
            res["msg"] = "OK"
            res["data"] = data
        except Exception as err:
            res["msg"] = str(err)
        return res


@app.route("/", methods=["GET", "POST"])
def process():
    # 获取opt的值
    opt = flask.request.values.get("opt") if "opt" in flask.request.values else ""
    res = {}
    # 创建数据库
    db = StudentDB()
    db.openDB()
    if opt == "init":
        res = db.initTable()
    elif opt == "insert":
        id = flask.request.values.get("id") if "id" in flask.request.values else ""
        name = flask.request.values.get("name") if "name" in flask.request.values else ""
        grade = flask.request.values.get("grade") if "grade" in flask.request.values else ""
        res = db.insertRow(id, name, grade)
    elif opt == "delete":
        id = flask.request.values.get("id") if "id" in flask.request.values else ""
        res = db.deleteRow(id)
    elif opt == "update":
        id = flask.request.values.get("id") if "id" in flask.request.values else ""
        res = db.updateRow(id)
    else:
        res = db.selectRows()
    db.closeDB()
    return json.dumps(res)


if __name__ == '__main__':
    app.run()

3.客户端程序


客户端程序client.py如下:

import urllib.request
import urllib.parse
import json


# 创建一个student的对象
class Student:
    def __init__(self, id, name, grade):
        self.id = id
        self.name = name
        self.grade = grade

    def show(self):
        # 打印方法
        print("%-16s %-16s %-4d" % (self.id, self.name, self.grade))


students = []
# server的网址
url = "http://127.0.0.1:5000"


# 显示主功能界面
def main():
    print("=" * 15 + "主界面" + "=" * 14)
    print("*" * 10 + "1-添加学生信息" + "*" * 10)
    print("*" * 10 + "2-删除学生信息" + "*" * 10)
    print("*" * 10 + "3-修改学生信息" + "*" * 10)
    print("*" * 10 + "4-查询学生信息" + "*" * 10)
    print("*" * 10 + "5-显示所有学生信息" + "*" * 7)
    print("*" * 10 + "6-初始化学生列表" + "*" * 8)
    print("*" * 10 + "0-退出系统" + "*" * 13)
    print("=" * 33)


# 初始化
# 如果客户端向服务端发送opt="init",那么服务器创建students表,并返回是否创建成功,如果成功就返回{"msg":"OK"}
def initialize():
    st = ""
    try:
        content = urllib.request.urlopen(url + "?opt=init")
        st = content.read()
        st = json.loads(st.decode())
        st = st["msg"]
    except Exception as err:
        st = str(err)

    if st == "OK":
        print("初始成功")
    else:
        print(st)
    return st


# 插入学生记录
# 如果客户端向服务器发送opt="insert",同时发送id、name、grade参数,那么服务器向数据库表插入一条学生记录,并返回是否插入成功信息,如果如果成功就返回{"msg":"OK"}
def insertRow():
    # 获取学生的学号、姓名、成绩
    id = input("id=")
    name = input("name=")
    while True:
        grade = int(input("grade="))
        if 0 <= grade <= 100:
            break
        else:
            print("无效成绩!\n请重新输入 范围:0~100")

    if id != "" and name != "":
        s = Student(id, name, grade)
        for x in students:
            if x.id == id:
                print(id + "已经存在")
                return
        st = ""
        try:
            # 调用远程数据
            st = "id=" + urllib.parse.quote(id) + \
                 "&name=" + urllib.parse.quote(name) + \
                 "&grade=" + str(grade)
            st = st.encode()
            content = urllib.request.urlopen(url + "?opt=insert", st)
            st = content.read()
            st = json.loads(st.decode())
            st = st["msg"]
        except Exception as err:
            st = str(err)
        if st == "OK":
            insertStudent(s)
            print("添加成功")
        else:
            print(st)
    else:
        print("学号、姓名不能为空")


# 插入学生记录
def insertStudent(s):
    global students
    i = 0
    while i < len(students) and s.id > students[i].id:
        i += 1
    # 判断表格里面是否存在
    if i < len(students) and s.id == students[i].id:
        print(s.id + "已经存在")
        return False
    students.insert(i, s)
    return True


# 删除学生记录
# 如果客户端向服务器发送opt="delete",同时发送id参数,那么服务器从数据库表中删除学号为id的一条学生记录,并返回是否删除成功的信息,如果如果成功就返回{"msg":"OK"}
def deleteRow():
    global students
    id = input("id=")
    if id != "":
        for i in range(len(students)):
            if students[i].id == id:
                st = ""
                try:
                    st = "id=" + urllib.parse.quote(id)
                    st = st.encode()
                    # 找到id就调用urllib.request.urlopen
                    content = urllib.request.urlopen(url + "?opt=delete", st)
                    st = content.readline()
                    # 通过json解析数据
                    st = json.loads(st.decode())
                    st = st["msg"]
                except Exception as err:
                    st = str(err)

                if st == "OK":
                    del students[i]
                    print("删除成功")
                else:
                    print(st)
                break


# 更新学生信息
def updateRow():
    pass


# 查询学生信息
def selectRow():
    pass


# 读取学生记录
def readStudents():
    global students
    try:
        students.clear()
        content = urllib.request.urlopen(url)
        data = b""  # 二进制str变量
        while True:
            buf = content.read(1024)  # 每次读取1024字节内容,并且指针指向末尾
            if len(buf) > 0:
                data += buf
            else:
                break
        data = data.decode()  # 解码 UTF-8
        # 反系列结构化的数据
        data = json.loads(data)
        if data["msg"] == "OK":
            data = data["data"]  # data["data"]=[row0,row1.row2...]
            for d in data:
                # 每个d都是一个字典
                s = Student(d["id"], d["name"], d["grade"])
                students.append(s)
    except Exception as err:
        print(err)


# 显示所有的学生
def listStudents():
    global students
    print("%-16s %-16s %-4s" % ("id", "name", "grade"))
    for s in students:
        # 调用show函数
        s.show()


try:
    readStudents()
    while True:
        main()  # 打印菜单
        s = int(input("请选择(0,1,2,3,4,5,6):"))
        if s == 0:  # 退出系统
            break
        elif s == 1:  # 添加学生信息
            insertRow()
        elif s == 2:  # 删除学生信息
            deleteRow()
        elif s == 3:  # 修改学生信息
            updateRow()
        elif s == 4:  # 查询学生信息
            selectRow()
        elif s == 5:  # 显示所有学生信息
            listStudents()
        elif s == 6:
            initialize()  # 初始化学生列表
except Exception as exp:
    print(exp)

客户端结果实例:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/337928.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单目相机、双目相机和RGB-D相机学习笔记(一些视频和博文网址)

目录1. 单目相机1.1 摄像头原理1.2 单目相机的标定2 双目相机2.1 双目相机定位原理2.2 双目相机的缺陷3 RGB-D相机3.1 深度相机结构光原理3.2 RGB-D相机的应用1. 单目相机 1.1 摄像头原理 视频网址&#xff1a;【全网最详细】摄像头原理分析&#xff08;约25分钟课程&#xf…

RPC框架设计的安全性考量

RPC里面该如何提升单机资源的利用率&#xff0c;你要记住的关键点就一个&#xff0c;那就是“异步化”。调用方利用异步化机制实现并行调用多个服务&#xff0c;以缩短整个调用时间&#xff1b;而服务提供方则可以利用异步化把业务逻辑放到自定义线程池里面去执行&#xff0c;以…

springboot 注解

上一篇&#xff1a;初识springboot接收参数常用注解RequestBody 常用于POST表单提交参数接收RequestMapping("/test") public String test(RequestBody String data){return data; }PathVariable 获取路径上的参数&#xff1a;/test/{id} RequestMapping("/test…

开源流程引擎Camunda

开源流程引擎Camunda 文章作者&#xff1a;智星 1.简介 Camunda是一个轻量级的商业流程开源平台&#xff0c;是一种基于Java的框架&#xff0c;持久层采用Mybatis&#xff0c;可以内嵌集成到Java应用、SpringBooot应用中&#xff0c;也可以独立运行&#xff0c;其支持BPMN&a…

ThingsBoard-规则引擎介绍

1、什么是规则引擎? 规则引擎是一个易于使用的框架,用于构建基于事件的工作流。有3个主要组成部分: 消息- 任何传入事件。它可以是来自设备的传入数据、设备生命周期事件、REST API 事件、RPC 请求等。规则节点- 对传入消息执行的功能。有许多不同的节点类型可以过滤、转换…

微信 API 中调用客服消息接口提示错误返回限制

错误的信息如下&#xff1a;errcode45015, errmsgresponse out of time limit or subscription is canceled rid: 5f8fd8b7-0f8aa1a9-4b6215a5微信的文档看着这微信不清不楚的文档&#xff1a;微信公众平台在这个文档界面中&#xff0c;有句话&#xff1a;这句话&#xff0c;我…

【信息学CSP-J近16年历年真题64题】真题练习与解析 第13题之标题统计

标题统计 描述 凯凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符? 注意:标题中可能包含大、小写英文字母、数字字符、空格和换行符。统计标题字符数时,空格和换行符不计算在内。 输入 输入文件只有一行,一个字符串 s。 输出 输出文件只有一行,包含一个整…

原型、原型链、__proto__与prototype的区别、继承

一.什么是原型与原型链 根据MDN官方解释: JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象[[Prototype]] &#xff0c;对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型&#xff0c;并从中继承方法和属性&#xff0c;一层一层、以此类…

Kafka第二章:生产者案例

系列文章目录 Kafka第一章&#xff1a;环境搭建 Kafka第二章&#xff1a;生产者案例 文章目录系列文章目录前言一、创建项目1.创建包2.添加依赖二、编写代码1.普通异步发送2.同步发送三.生产者发送消息的分区策略1.指定分区2.自定义分区总结前言 上次完成了Kafka的环境搭建&a…

RabbitMQ-Exchanges交换机

一、介绍 RabbitMQ消息传递模型的核心思想是&#xff1a;生产者生产的消息从不会直接发送到队列。实际上&#xff0c;通常生产者甚至不知道这些消息传递到了哪些队列中。相反&#xff0c;生产者只能将消息发送到交换机&#xff0c;交换机工作的内容非常简单&#xff0c;一方…

七、Java框架之MyBatisPlus

黑马课程 文章目录1. MyBatisPlus入门1.1 MyBatisPlus入门案例步骤1&#xff1a;创建spring boot工程步骤2&#xff1a;配置application.yml步骤3&#xff1a;创建数据库表&#xff08;重点&#xff09;步骤4&#xff1a;编写dao层步骤5&#xff1a;测试1.2 标准数据层开发标准…

CSDN每日一练:一维数组的最大子数组和

题目名称&#xff1a;一维数组的最大子数组和 时间限制&#xff1a;1000ms内存限制&#xff1a;256M 题目描述 下面是一个一维数组的 “最大子数组的和” 的动态规划的解法 # include <iostream> # include <stdio.h> # include <string.h>int MaxSum(int* a…

多传感器融合定位十五-多传感器时空标定(综述)

多传感器融合定位十五-多传感器时空标定1. 多传感器标定简介1.1 标定内容及方法1.2 讲解思路2. 内参标定2.1 雷达内参标定2.2 IMU内参标定2.3 编码器内参标定2.4 相机内参标定3. 外参标定3.1 雷达和相机外参标定3.2 多雷达外参标定3.3 手眼标定3.4 融合中标定3.5 总结4. 时间标…

基于live555源码的rtsp服务器

下载live555源码 http://www.live555.com/liveMedia/public/ 在Linux系统的自定义目录下输入&#xff0c;下载源码&#xff1a; wget http://www.live555.com/liveMedia/public/live.2023.01.19.tar.gz解压源码&#xff1a; tar -xvf live.2023.01.19.tar.gz当前目录下运行&…

前端卷算法系列(一)

前端卷算法系列&#xff08;一&#xff09; 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同…

无重复字符的最长子串-力扣3-java

一、题目描述给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。示例 1:输入: s "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。示例 2:输入: s "bbbbb"输出: 1解释: 因为…

Springboot Web开发

文章目录一. 静态资源访问1. 配置静态资源访问前缀2. 修改默认静态资源存放目录3. Webjars4. 欢迎页支持5. 自定义Favicon二. 请求处理1. 路径变量2. 请求头处理3. 查询字符串处理4. 获取Cookie的值5. 获取请求体的值6. 获取请求域中的数据7. 矩阵变量一. 静态资源访问 只要静…

ChatGPT全球爆火,究竟有何特别之处?

​ 新年复工不过半月&#xff0c;职场人似乎就受到了来自AI的“威胁”&#xff0c;关于人工智能聊天系统ChatGPT的热搜频频上榜。 ChatGPT不仅拟人&#xff0c;更类人&#xff0c;甚至被认为是职场人的“敌人”。 那么&#xff0c;ChatGPT能替代哪些职业&#xff1f; 它自己的回…

STP协议基础

STP协议技术来源二层环路及危害二层交换机网络的冗余性与环路人为错误导致的二层环路二层环路带来的问题STP生成树协议STP概述STP基本概念桥ID根桥COSTRPC&#xff08;Root Path Cost&#xff09;根路径开销PORT ID端口IDBPDU桥协议数据单元STP的计算过程&#xff08;1&#xf…

VS中安装gismo库

文章目录前言一、下载安装paraview直接下载压缩包安装就可以了解压后按步骤安装即可二、gismo库的安装gismo库网址第一种方法&#xff1a;第二种方法第三种方法&#xff1a;用Cmake软件直接安装首先下载cmake软件[网址](https://cmake.org/download/)安装gismo库三、gismo库的使…