苦恼的朋友
最近,我的朋友非常没有精神,经常闷闷不乐,我感觉他的状态很不好,于是关切他到底怎么了,然后他就和我说了他遇到的困惑
他:今年年初开始,我一直在学习编程,眼看着现在已经6月多了,半年多过去了,可是我还是只会写“黑窗口”的程序,我感觉很没有用,不知道能做什么,为什么我只能写这样的程序呢,这样的程序有什么用呢?
我:那你写了什么样的“黑窗口”程序呢?
他:比如说,我学会写了“学生管理系统”的程序,我的代码是这样写的
class StudentSystem:
def __init__(self):
self.students = dict()
def add_student(self, name, age):
if name in self.students:
print(f"{name}已经存在,不可以添加同名学生")
else:
self.students[name] = age
print(f"已经成功添加了学生,姓名:{name}")
def all_students(self):
for name in self.students:
print(f"学生,姓名:{name},年龄:{self.students[name]}")
def find_student(self, name):
if name in self.students:
print(f"学生,姓名:{name},年龄{self.students[name]}")
else:
print(f"没有找到名为{name}的学生")
def main(self):
while 1:
print("\n****\t欢迎来到学生管理系统!\t****")
print("****\t1. 添加学生\t****")
print("****\t2. 查看所有学生\t****")
print("****\t3. 查找一个学生\t****")
print("****\t4. 退出系统\t****")
c = input("请选择一个选项 (1-4): ")
if c == "1":
name = input("请输入学生的名字: ")
age = input("请输入学生的年龄: ")
self.add_student(name, age)
elif c == "2":
self.all_students()
elif c == "3":
name = input("请输入要查找的学生的名字: ")
self.find_student(name)
elif c == "4":
print("感谢您使用我们的系统!欢迎下次光临!")
break
else:
print("您输入的有误呢,请输入正确的选项(1-4)")
if __name__ == "__main__":
s = StudentSystem()
s.main()
他:这个代码运行以后的效果就像是这样的
我:你这个代码写的很厉害啊,你这个可是使用了“面向对象”的程序设计,将所有的代码都封装到了一个类中,是非常好的实现啊,为什么你不满意呢?
他:可是没有用啊,这样的程序,虽然是我花了很长的时间才写出来的,但是谁会用呢?谁会去使用这样的程序呢?
我:你这样想就不对了,如果你把你的程序改写为“微信小程序”,就可以发挥出很大的作用了,在现实世界中,有很多很多的人都会使用这样的程序,你和他们的区别只是在于用户界面不一样罢了,没什么值得灰心丧气的!
他:微信小程序很厉害,我也经常使用,甚至出门吃饭,买东西都要用,可是我还是不知道我写的程序怎么才能够做成微信小程序,我该怎么做呢?
这没什么困难的,今天,我们就以朋友的这个学生管理系统为基础,将其改写为微信小程序的学生管理系统
系统设计
很多人可能有一个错误的想法,也就是认为实现一个学生管理系统,是很没有用的,做不了什么事情,既不能用于工作,也没有实际的使用价值,这个想法是不对的。这样的系统是否有使用价值,取决于我们对其的设计,事实上,如果我们设计的功能较为完善,是完全可以使其拥有使用价值的。
例如说,我们通过创建账户,以及划分职责,分别创建学生,教师和管理员的账户,还需要可以实现以下的功能:
- 学生信息管理:管理学生的信息(包括姓名、性别、生日、联系方式、所属班级、年级),其中允许管理员添加、修改和删除学生信息
- 教师信息管理:管理教师的信息(包括姓名、性别、生日、联系方式),其中,一个教师也可能教授多个年级和班级,同样允许管理员添加、修改和删除教师信息
- 课程信息管理:管理员可以添加、修改和删除课程信息,包括课程名称、课程描述、授课老师、上课时间和地点。
- 成绩管理:学生可以查看他们的成绩,教师可以添加和修改学生的成绩。
- 考勤管理:教师可以记录学生的出勤情况,包括迟到、早退、请假和缺席。
- 作业通知:教师可以布置作业,学生可以提交作业,教师可以批改并评分。
- 通知与公告:管理员和教师可以发布校园新闻、活动公告和重要通知。
当然,即便现在已经包含了很多的功能,也还是可以扩展添加更多的功能的。比如说,学习资料和文件的上传与下载,课程视频的上传与观看,讨论区/答疑区/论坛的创建与建设等等。通过不断的添加更多的功能,完善系统,就可以做出非常有用的程序,而非一般人认为的“毫无价值”。
当然,介于时间的缘故,因此这次我们只实现以上设计出的7个主要功能,后续如果有需要,还可以根据主要功能,进行扩展和添加
数据存储
根据我们希望实现的功能,可以设计出对应的存储结构
1.学生表 :存储学生的信息。
id:学生ID,主键
name:学生的姓名
gender:学生的性别
birthday:学生的出生日期
phone:学生的联系方式
grade:学生所在的年级
class:学生所在的班级
2.教师表 :存储教师的信息。
id:教师ID,主键
name:教师的姓名
gender:教师的性别
birthday:教师的出生日期
phone:教师的联系方式
3.课程表 :存储课程的信息。
id:课程ID,主键
name:课程名称
description:课程描述
teacher_id:授课教师的ID,外键,应当关联教师表的id
course_info:上课时间和地点
4.成绩表 :存储学生的成绩。
id:成绩ID,主键
student_id:学生的ID,外键,应当关联学生表的id
course_id:课程的ID,外键,应当关联课程表的id
grade:成绩
5.出勤表 :存储学生的出勤情况。
id:出勤记录ID,主键
student_id:学生的ID,外键,应当关联学生表的id
course_id:课程的ID,外键,应当关联课程表的id
status:出勤状态
date:出勤日期
6.作业表:存储作业通知。
id:作业ID,主键
course_id:课程的ID,外键,应当关联课程表的id
description:作业描述
end_date:截止日期
7.通知表 :存储通知和公告。
id:通知ID,主键
title:通知标题
content:通知内容
date:发布日期
在选择了合适的字段类型以后,就可以根据先前的设计,创建出所需的数据表
1.学生表
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
gender ENUM('male', 'female'),
birthday DATE,
phone VARCHAR(15),
grade INT,
class INT );
2.教师表
CREATE TABLE teachers (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
gender ENUM('male', 'female'),
birthday DATE,
phone VARCHAR(15)
);
3.课程表
CREATE TABLE courses (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
description TEXT,
teacher_id INT,
course_info VARCHAR(250),
FOREIGN KEY (teacher_id) REFERENCES teachers(id)
);
4.成绩表
CREATE TABLE grades (
id INT AUTO_INCREMENT PRIMARY KEY,
student_id INT,
course_id INT,
grade FLOAT,
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
5.出勤表
CREATE TABLE attendance (
id INT AUTO_INCREMENT PRIMARY KEY,
student_id INT,
course_id INT,
status ENUM('attend', 'late', 'absent'),
date DATE,
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
6.作业表
CREATE TABLE homework (
id INT AUTO_INCREMENT PRIMARY KEY,
course_id INT,
description TEXT,
end_date DATE,
FOREIGN KEY (course_id) REFERENCES courses(id)
);
7.通知表
CREATE TABLE news (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(250),
content TEXT,
date DATE
);
接口设计
针对以上的功能,我们可以设计出以下的接口
1. 学生信息管理:
GET /students:获取所有学生的信息
GET /students/{studentId}:获取指定ID的学生的信息
GET /students/{studentName}:获取指定姓名的学生的信息
GET /students/{studentPhone}:获取指定联系方式的学生的信息
POST /students:添加新的学生信息
PUT /students/{studentId}:更新指定ID的学生的信息
DELETE /students/{studentId}:删除指定ID的学生的信息
2.教师信息管理:
GET /teachers:获取所有教师的信息
GET /teachers/{teacherId}:获取指定ID的教师的信息
GET /teachers/{teacherName}:获取指定姓名的教师的信息
GET /teachers/{teacherPhone}:获取指定联系方式的教师的信息
POST /teachers:添加新的教师信息
PUT /teachers/{teacherId}:更新指定ID的教师的信息
DELETE /teachers/{teacherId}:删除指定ID的教师的信息
3.课程信息管理:
GET /courses:获取所有课程的信息
GET /courses/{courseId}:获取指定ID的课程的信息
POST /courses:添加新的课程信息
PUT /courses/{courseId}:更新指定ID的课程的信息
DELETE /courses/{courseId}:删除指定ID的课程的信息
4.成绩管理:
GET /students/{studentId}/grades:获取指定学生的所有成绩
POST /students/{studentId}/grades:添加指定学生的新成绩
PUT /students/{studentId}/grades/{gradeId}:更新指定学生的指定成绩
DELETE /students/{studentId}/grades/{gradeId}:删除指定学生的指定成绩
5.考勤管理:
GET /students/{studentId}/attendance:获取指定学生的出勤情况
POST /students/{studentId}/attendance:添加指定学生的出勤记录
PUT /students/{studentId}/attendance/{attendanceId}:更新指定学生的指定出勤记录
DELETE /students/{studentId}/attendance/{attendanceId}:删除指定学生的指定出勤记录
6.作业通知:
GET /homework:获取所有作业通知
GET /homework/{homeworkId}:获取指定ID的作业通知
POST /homework:添加新的作业通知
PUT /homework/{homeworkId}:更新指定ID的作业通知
DELETE /homework/{homeworkId}:删除指定ID的作业通知
7.通知与公告:
GET /news:获取所有通知和公告
GET /news/{newsId}:获取指定ID的通知或公告
POST /news:添加新的通知或公告
PUT /news/{newsId}:更新指定ID的通知或公告
DELETE /news/{newsId}:删除指定ID的通知或公告
可以看到这里,我们分别使用了GET,POST,PUT和DELETE四种请求方式,可能很多人会认为使用这么多种请求方式没有必要,反而麻烦,只使用GET和POST就可以了。
其实不然,多种请求方式的使用是有好处的,如果我们只使用GET和POST请求,那么,以学生信息为例
GET /students/{studentId}:获取指定ID的学生的信息
POST /students:添加新的学生信息
PUT /students/{studentId}:更新指定ID的学生的信息
DELETE /students/{studentId}:删除指定ID的学生的信息
此时,我们就无法再使用相同的接口地址/students/{studentId},必须修改为
GET /get_students/{studentId}:获取指定ID的学生的信息
POST /add_students:添加新的学生信息
POST /modify_students/{studentId}:更新指定ID的学生的信息
GET /delete_students/{studentId}:删除指定ID的学生的信息
很显然,这种修改方式即使每个都起了对应的名字,也是不如直接使用PUT,DELETE这样的请求方法直观而清晰的。因此,在实践中,选择合适的请求方法也是必要的,并非总是只使用GET和POST两种请求
也可以看到,这里我们分别使用了多个不同的接口,来分别对应不同的功能,如下所示
GET /students/{studentId}:获取指定ID的学生的信息
GET /students/{studentName}:获取指定姓名的学生的信息
GET /students/{studentPhone}:获取指定联系方式的学生的信息
当然,如果不喜欢增加接口的数量的话,也可以选择使用请求参数的方式,例如
GET /get_students:获取学生的学生信息
GET /get_students?id=指定ID
GET /get_students?name=姓名
GET /get_students?phone=电话
页面制作
同样的,根据我们希望实现的功能,制作所需要的微信小程序的页面,这些页面都应该添加到pages中
- 首页(index):在首页上可以展示放置重要的通知和公告,也可以展示当前使用的用户的基本信息,如姓名、班级。
- 登录页(login):用户可以通过此页面登录,需要通过微信小程序授权登录
- 学生信息页(students):该页面用于展示学生的所有信息。如果用户是管理员的话,还可以在这个页面上添加、修改和删除学生信息。
- 教师信息页(teachers):该页面用于展示教师的所有信息。如果用户是管理员的话,还可以在这个页面上添加、修改和删除教师信息。
- 课程信息页(courses):该页面用于展示课程的所有信息。如果用户是管理员的话,还可以在这个页面上添加、修改和删除课程信息。
- 成绩页(grades):该页面用于展示学生的所有成绩。如果用户是教师的话,还可以在这个页面上添加和修改学生成绩。
- 出勤页(attendance):该页面展示学生的所有出勤记录。如果用户是教师的话,还可以在这个页面上添加和修改出勤的记录。
- 作业页(homework):该页面展示所有作业通知。学生可以在此页面上查看作业,教师可以在此页面上发布和批改作业。
最终结果
朋友看完了我做的微信小程序的学生管理系统以后,不禁连连称奇,“真没想到,扩展了功能,更换了显示方式以后,一个简单的学生管理系统,都可以发挥出这么大的作用,编程真是太棒了。现在我终于找到了学习的方向了,知道以后该怎么做了。今后,我也要学习制作微信小程序。”
看着朋友重新振作起来,我也是非常的欣慰,其实学习编程就是这样,看起来很不起眼,“没什么用”的知识,其实未来都能够发挥出大作用。因此,对于程序的初学者来说,仅仅是一时写的程序不能够真正的在现实中使用,是很正常的,完全不需要心灰意冷。重要的是,学习到了这些“黑窗口”的知识,未来有一天,都能够在更广阔的天空下发挥作用。