Python课程实训之学生成绩分析系统

一、实践名称

学生成绩分析系统课程设计

二、实践目的

  1. 掌握数据帧的创建和切片方法;
  2. 掌握数据的预处理方法;
  3. 掌握Matplotlib的常用绘图方法;
  4. 掌握GUI窗体的创建方法;
  5. 掌握常用控件的使用;
  6. 掌握信号/槽编程方法;
  7. 掌握多窗体设计方法;
  8. 掌握进行项目功能测试、边界测试、黑盒测试和白盒测试的基本方法;
  9. 让学生在不断试错与纠错中成长,学会分析与解决实际工作中遇到的问题,提升抗挫能力。
  10. DataFrame的工作原理;
  11. DataFrame的常用数据处理函数和数据处理方法;
  12. 面向对象的编程方法;
  13. Matplotlib的工作原理;
  14. Matplotlib绘制柱状图的基本方法;Python GUI设计的基本方法;
  15. Python GUI 设计中的常用控件的属性;
  16. Python GUI 设计中的事件响应机制;
  17. 测试的基本原理。

本次开发基于python来做一个数据分析开发系统 ,前提是有一个data.csv文件,其他文件也可以自行修改

登录界面,可以登录,注册,通过电话号码找回密码等操作。账号密码自动会存在一个文本框里

class LoginWindow(tk.Toplevel):
    def __init__(self, master=None):
        super().__init__(master)
        self.title("登录")
        self.geometry("250x150")
        self.username_label = tk.Label(self, text="用户名:")
        self.password_label = tk.Label(self, text="密码:")
        self.username_entry = tk.Entry(self)
        self.password_entry = tk.Entry(self, show="*")
        self.login_button = tk.Button(self, text="登录", command=self.login)
        self.register_button = tk.Button(self, text="注册", command=self.collect_phone)
        self.forgot_password_button = tk.Button(self, text="找回密码", command=self.find)
        self.username_label.grid(row=0, column=0, padx=5, pady=5)
        self.password_label.grid(row=1, column=0, padx=5, pady=5)
        self.username_entry.grid(row=0, column=1, padx=5, pady=5)
        self.password_entry.grid(row=1, column=1, padx=5, pady=5)
        self.login_button.grid(row=2, column=0, padx=5, pady=5)
        self.register_button.grid(row=2, column=1, padx=5, pady=5)
        self.forgot_password_button.grid(row=3, column=0, columnspan=2, padx=5, pady=5)

        self.users_file = "users.txt"
        if not os.path.exists(self.users_file):
            with open(self.users_file, "w") as file:
                file.write("{}")

        self.protocol("WM_DELETE_WINDOW", self.close_app)

    def login(self):
        username = self.username_entry.get()
        password = self.password_entry.get()
        users = self.load_users()
        if username in users and users[username]["password"] == password:
            messagebox.showinfo("登录成功", "登录成功!")
            self.destroy()
            self.master.has_permission = True
        elif username == "admin" and password == "admin":
            messagebox.showinfo("登录成功", "登录成功!")
            self.destroy()
            self.master.has_permission = True
        else:
            messagebox.showerror("登录失败", "用户名或密码错误")

    def load_users(self):
        try:
            with open(self.users_file, "r") as file:
                users = json.load(file)
        except (FileNotFoundError, json.JSONDecodeError):
            users = {}

        return users

    def find(self):
        username = simpledialog.askstring("找回密码", "请输入用户名:")
        phone = simpledialog.askstring("找回密码", "请输入电话号码:")
        users = self.load_users()
        if username in users and users[username]["phone"] == phone:
            password = users[username]["password"]
            messagebox.showinfo("找回密码", f"您的密码是: {password}")
        else:
            messagebox.showerror("找回密码失败", "用户名或电话号码不匹配")

    def save_users(self, users):
        with open(self.users_file, "w") as file:
            json.dump(users, file)

    def collect_phone(self):
        username = self.username_entry.get()
        password = self.password_entry.get()
        if not username or not password:
            messagebox.showerror("注册失败", "请输入用户名和密码")
            return
        phone = simpledialog.askstring("输入电话号码", "请输入电话号码:")
        self.register(phone)

    def register(self, phone):
        username = self.username_entry.get()
        password = self.password_entry.get()
        if not username or not password:
            messagebox.showerror("注册失败", "请输入用户名和密码")
        elif not phone:
            messagebox.showerror("注册失败", "请输入电话号码")
        else:
            users = self.load_users()
            if username in users:
                messagebox.showerror("注册失败", "用户名已被注册")
            else:
                users[username] = {"password": password, "phone": phone}
                self.save_users(users)
                messagebox.showinfo("注册成功", "注册成功!")

    def close_app(self):
        self.master.destroy()  # 关闭整个应用程序

 以上是登入这方面的类,给大家参考。

进入系统后,有三个页面,第一个是数据操作区,分析图展示,成绩汇总分析。

        self.title("学生成绩分析系统")
        self.has_permission = False
        self.tabControl = ttk.Notebook(self)
        self.undo_stack = []
        self.student_vars = []  # 用于存储学生选择的变量
        self.subject_vars = []
        self.colors = ['blue', 'green', 'red', 'cyan', 'magenta', 'yellow', 'black', 'purple', 'pink', 'brown']
        self.colorss = ['orange', 'blue', 'red']
        self.tab1 = ttk.Frame(self.tabControl)
        self.tab2 = ttk.Frame(self.tabControl)
        self.tab3 = ttk.Frame(self.tabControl)
        self.tab4 = ttk.Frame(self.tabControl)
        self.tabControl.add(self.tab1, text="数据操作区")
        self.tabControl.add(self.tab2, text="分析图展示")
        self.tabControl.add(self.tab3, text="成绩汇总分析")
        self.tabControl.pack(expand=1, fill="both")

        # Tab 1 - 数据操作
        self.tree = ttk.Treeview(self.tab1, columns=[f"col{i}" for i in range(4)], show="headings", selectmode="browse")
        self.tree.grid(row=0, column=0, columnspan=5, padx=5, pady=5)
        self.tree.heading("#0", text="ID")
        self.tree.heading("#1", text="姓名")
        self.tree.heading("#2", text="语文")
        self.tree.heading("#3", text="数学")
        self.tree.heading("#4", text="英语")
        # 设置列的宽度
        self.tree.column("#0", width=50, anchor='center')
        self.tree.column("#1", width=100, anchor='center')
        self.tree.column("#2", width=100, anchor='center')
        self.tree.column("#3", width=100, anchor='center')
        self.tree.column("#4", width=100, anchor='center')

        # 设置数据居中对齐的样式
        self.tree.tag_configure('center', anchor='center')
        self.btn_load = tk.Button(self.tab1, text="读取", command=self.load_data)
        self.btn_add = tk.Button(self.tab1, text="添加", command=self.show_add_window)
        self.btn_modify = tk.Button(self.tab1, text="修改", command=lambda: self.modify_data())
        self.btn_delete = tk.Button(self.tab1, text="删除", command=self.delete_data)
        self.btn_save = tk.Button(self.tab1, text="保存", command=self.save_data)
        self.back = tk.Button(self.tab1, text="撤回", command=self.undo)
        self.exsave = tk.Button(self.tab1, text="另存为", command=self.undo)
        self.btn_load.grid(row=1, column=0, padx=5, pady=5)
        self.btn_add.grid(row=1, column=1, padx=5, pady=5)
        self.btn_modify.grid(row=1, column=2, padx=5, pady=5)
        self.btn_delete.grid(row=1, column=3, padx=5, pady=5)
        self.btn_save.grid(row=1, column=4, padx=5, pady=5)
        self.back.grid(row=1, column=5, padx=5, pady=5)

        # Tab 2 - 柱状图展示
        self.students_frame = tk.Frame(self.tab2)
        self.subjects_frame = tk.Frame(self.tab2)
        self.students_frame.grid(row=1, column=1, padx=5, pady=5)
        self.subjects_frame.grid(row=2, column=1, padx=5, pady=5)
        self.students_label = Label(self.students_frame, text="学生")
        self.students_label.grid(row=0, column=0, padx=5, pady=5)
        self.subject_label = Label(self.subjects_frame, text="学科")
        self.subject_label.grid(row=1, column=0, padx=5, pady=5)
        self.button7 = tk.Button(self.tab2, text="绘制柱状图", command=self.draw_bar_chart)
        self.button7.grid(row=3, column=1, padx=5, pady=5)

        self.plot_area = tk.Label(self.tab2)
        self.plot_area.grid(row=1, columnspan=3, padx=5, pady=5)

        # Tab 3 - 成绩分析
        self.btn_avg_score = tk.Button(self.tab3, text="课程平均分", command=self.show_avg_score)
        self.btn_max_score = tk.Button(self.tab3, text="课程最高分", command=self.show_max_score)
        self.btn_personal_max_min = tk.Button(self.tab3, text="个人最高分", command=self.show_personal_max_min)
        self.btn_avg_score.pack(pady=5)
        self.btn_max_score.pack(pady=5)
        self.btn_personal_max_min.pack(pady=5)

第一个是用来读取数据后进行增删改查等操作,以及点击保存后才会保存和撤回删除这个操作。代码如下 

    def load_data(self):
        file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
        if file_path:
            data = pd.read_csv(file_path)
            self.tree.delete(*self.tree.get_children())
            with open(file_path, "r", newline="", encoding="utf-8") as csvfile:
                reader = csv.reader(csvfile)
                first_line = next(reader)
                first_line_str = ",".join(first_line)

            self.tree.heading("#0", text=first_line_str)
            self.tree.heading("#1", text=first_line_str[0:2])
            self.tree.heading("#2", text=first_line_str[3:5])
            self.tree.heading("#3", text=first_line_str[6:8])
            self.tree.heading("#4", text=first_line_str[9:11])

      

    def add_data(self):
        # 在文本框中添加数据
        cursor_id = self.tree.selection()
        if cursor_id:
            last_id = self.tree.index(cursor_id[-1]) + 1
        else:
            last_id = len(self.tree.get_children())

        data_1 = self.entry_1.get()
        data_2 = self.entry_2.get()
        data_3 = self.entry_3.get()
        data_4 = self.entry_4.get()

        # 在树形列表中插入新行
        last_id = len(self.tree.get_children())
        self.tree.insert("", "end", text=last_id + 1, values=[data_1, data_2, data_3, data_4])

        # self.tree.insert("", last_id, text=last_id, values=["", "", "", ""])

    def show_add_window(self):
        # 创建添加窗口
        self.add_window = tk.Toplevel(self.master)
        self.add_window.title("添加数据")
        self.check_label1_1 = tk.Label(self.add_window, text="姓名", )
        self.check_label2_2 = tk.Label(self.add_window, text="语文", )
        self.check_label3_3 = tk.Label(self.add_window, text="数学", )
        self.check_label4_4 = tk.Label(self.add_window, text="英语", )
        self.check_label1_1.grid(row=0, column=0, padx=5, pady=5)
        self.check_label2_2.grid(row=0, column=1, padx=5, pady=5)
        self.check_label3_3.grid(row=0, column=2, padx=5, pady=5)
        self.check_label4_4.grid(row=0, column=3, padx=5, pady=5)
        # 创建输入框
        self.entry_1 = tk.Entry(self.add_window)
        self.entry_2 = tk.Entry(self.add_window)
        self.entry_3 = tk.Entry(self.add_window)
        self.entry_4 = tk.Entry(self.add_window)
        self.entry_1.grid(row=2, column=0, padx=5, pady=5)
        self.entry_2.grid(row=2, column=1, padx=5, pady=5)
        self.entry_3.grid(row=2, column=2, padx=5, pady=5)
        self.entry_4.grid(row=2, column=3, padx=5, pady=5)

        # 创建添加按钮
        self.btn_add_data = tk.Button(self.add_window, text="添加", command=self.add_data)
        self.btn_add_data.grid(row=3, column=1, padx=5, pady=5)

    def modify_data(self):
        math_var = tk.StringVar()
        messagebox.showinfo("提示", "双击修改数据")

        # 编辑选中的行
        def edit_item():
            # 获取选中行的数据
            selected_item = self.tree.selection()[0]
            selected_data = self.tree.item(selected_item)['values']

            # 创建一个新的窗口
            edit_window = tk.Toplevel(self.tab1)
            edit_window.title("编辑")

            # 添加标签和文本框
            math_label = tk.Label(edit_window, text="数学:")
            math_label.grid(row=0, column=0, padx=5, pady=5)
            math_var = tk.StringVar(value=str(selected_data[2]))
            math_entry = tk.Entry(edit_window, textvariable=math_var)
            math_entry.grid(row=0, column=1, padx=5, pady=5)

            chinese_label = tk.Label(edit_window, text="语文:")
            chinese_label.grid(row=1, column=0, padx=5, pady=5)
            chinese_var = tk.StringVar(value=str(selected_data[1]))
            chinese_entry = tk.Entry(edit_window, textvariable=chinese_var)
            chinese_entry.grid(row=1, column=1, padx=5, pady=5)

            english_label = tk.Label(edit_window, text="英语:")
            english_label.grid(row=2, column=0, padx=5, pady=5)
            english_var = tk.StringVar(value=str(selected_data[3]))
            english_entry = tk.Entry(edit_window, textvariable=english_var)
            english_entry.grid(row=2, column=1, padx=5, pady=5)

            name_label = tk.Label(edit_window, text="姓名:")
            name_label.grid(row=3, column=0, padx=5, pady=5)
            name_var = tk.StringVar(value=str(selected_data[0]))
            name_entry = tk.Entry(edit_window, textvariable=name_var)
            name_entry.grid(row=3, column=1, padx=5, pady=5)

            # 保存数据
            def save_data():
                new_math_score = math_var.get()
                new_chinese_score = chinese_var.get()
                new_english_score = english_var.get()
                new_name = name_var.get()
                self.tree.set(selected_item, column=0, value=new_name)
                self.tree.set(selected_item, column=1, value=new_chinese_score)
                self.tree.set(selected_item, column=2, value=new_math_score)
                self.tree.set(selected_item, column=3, value=new_english_score)

                edit_window.destroy()

            # 添加一个按钮用于保存修改后的数据
            save_button = tk.Button(edit_window, text="保存", command=save_data)
            save_button.grid(row=4, column=1, padx=5, pady=5)

        # 双击树型列表中的一行时编辑该行的数据
        def on_double_click(event):
            edit_item()

        self.tree.bind("<Double-Button-1>", on_double_click)

    def delete_data(self):
        cur_item = self.tree.focus()
        if not cur_item:
            messagebox.showwarning("提示", "请先选择一行数据")
            return
        # 使用 item 方法获取当前选中项的相关信息
        cur_text = self.tree.item(cur_item)["text"]
        cur_values = self.tree.item(cur_item)["values"]
        # 使用 delete 方法删除当前选中项
        self.tree.delete(cur_item)
        messagebox.showinfo("提示", f"已删除数据:{cur_text}, {cur_values}")
        self.undo_stack.append((cur_item, cur_text, cur_values))

    def save_data(self):
        with open('data.csv', mode='w', newline='', encoding="utf-8") as file:
            writer = csv.writer(file)

            # 写入表头
            columns = [self.tree.heading(column)["text"] for column in self.tree["columns"]]
            writer.writerow(columns)

            # 写入数据
            for item_id in self.tree.get_children():
                row_data = []
                for column in self.tree["columns"]:
                    cell_data = self.tree.set(item_id, column)
                    row_data.append(cell_data)

                writer.writerow(row_data)

 第二部分就是把从文件读取学生的姓名和学科的姓名然后去根据下拉列表的多选去绘制柱状图

class CustomComboPicker(Frame):
    def __init__(self, master, values=[], **kwargs):
        super().__init__(master, **kwargs)
        self.values = values
        self.selected_values = []
        self.combo_frame = Frame(self)
        self.combo_frame.grid(row=0, column=3, padx=5, pady=5)
        self.combo_button = Button(self.combo_frame, text="请选择", command=self.show_dropdown)
        self.combo_button.grid(row=0, column=3, padx=5, pady=5)
        self.combo_label = Label(self.combo_frame, text="")
        # self.combo_label.pack(side=BOTTOM)

        self.dropdown_window = None

   
        if self.dropdown_window:
            self.hide_dropdown()
        else:
            self.dropdown_window = Toplevel(self)
            self.dropdown_window.geometry("+%d+%d" % (self.winfo_rootx() + self.winfo_width() // 2 - 75,
                                                      self.winfo_rooty() + self.winfo_height() // 2 - 100))
            self.dropdown_window.overrideredirect(True)

            self.listbox = Listbox(self.dropdown_window, selectmode=MULTIPLE)
            self.listbox.pack(fill=BOTH, expand=True)

            for value in self.values:
                self.listbox.insert(END, value)

            self.listbox.bind("<FocusOut>", self.hide_dropdown)

    
        if self.dropdown_window:
            selected_indices = self.listbox.curselection()
            if selected_indices:
                selected_values = [self.listbox.get(index) for index in selected_indices]
                self.selected_values = selected_values
                self.combo_label.configure(text=", ".join(selected_values))
                messagebox.showinfo("选中的数据", ", ".join(selected_values))
            else:
                self.selected_values = []
                self.combo_label.configure(text="")

            self.dropdown_window.destroy()
            self.dropdown_window = None

    def get_selected_values(self):
        return self.selected_values

绘图部分

    def draw_bar_chart(self):
        # 获取选中的学生和科目
        self.subject_picker.hide_dropdown()
        self.student_picker.hide_dropdown()
        selected_subjects = self.subject_picker.get_selected_values()
        selected_students = self.student_picker.get_selected_values()

        data = {}  # 存储选中学生的成绩数据
        with open('data.csv', 'r', encoding="utf-8") as file:
            reader = csv.DictReader(file)  # 使用DictReader读取csv文件
            for row in reader:
                student_name = row['姓名']  # 获取学生姓名
                if student_name in selected_students:  # 如果学生在选中的学生列表中
                    scores = []
                    for subject, score in row.items():
                        if subject != '姓名' and subject in selected_subjects:  # 如果科目不是姓名,并且在选中的科目列表中
                            scores.append(int(score))  # 将分数转换为整数并添加到分数列表中
                    data[student_name] = scores  # 将学生和对应的分数列表存储到data字典中

        if data:  # 如果有有效数据
            students = list(data.keys())  # 获取学生列表
            num_students = len(students)  # 学生数量
            subjects = selected_subjects  # 获取科目列表
            num_subjects = len(subjects)  # 科目数量

            # 创建图形和坐标轴对象
            fig, ax = plt.subplots()

            bar_width = 0.2
            index = 0
            for i, student in enumerate(students):
                scores = data[student]  # 获取学生对应的成绩列表
                x_pos = [index + j * bar_width for j in range(num_subjects)]
                bars = ax.bar(x_pos, scores, bar_width, label=student,
                              color=self.colors[i % len(self.colors)])  # 设置柱子颜色
                index += 1

                # 添加成绩标签
                for j, score in enumerate(scores):
                    ax.annotate(str(score), xy=(x_pos[j], score), va='bottom', ha='center')

               

            # 添加科目标签
            ax.set_xticks([index - bar_width / 2 + j * bar_width for j in range(num_subjects)])
            ax.set_xticklabels(subjects)

            # 创建图例
            handles = []
            for i, subject in enumerate(selected_subjects):
                patch = plt.Rectangle((0, 0), 1, 1, color=self.colorss[i % len(self.colors)], label=subject)
                handles.append(patch)
            ax.legend(handles=handles)

            # 设置图形属性
            ax.set_xlabel('学生')
            ax.set_ylabel('分数')
            ax.set_title('成绩柱状图')
            ax.set_xticks([index + bar_width / 2 for index in range(num_students)])
            ax.set_xticklabels(students)
            canvas = FigureCanvasTkAgg(fig, master=self.tab2)
            canvas.draw()
            canvas.get_tk_widget().grid(row=4, column=1, padx=10, pady=10)
        else:
            print("没有选择学生或科目")

最后选不同的学科和人去算平均分和最高分

  def show_avg_score(self):
        self.avg_window = tk.Toplevel(self.master)
        self.avg_window.title("平均值")

        window_width = 300
        window_height = 150
        screen_width = self.avg_window.winfo_screenwidth()
        screen_height = self.avg_window.winfo_screenheight()
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2
        self.avg_window.geometry(f"{window_width}x{window_height}+{x}+{y}")
        # 下拉列表
        subject_var = tk.StringVar()  # 存储所选科目
        subject_var.set("语文")  # 默认选择语文
        subject_options = ["语文", "数学", "英语"]
        subject_menu = tk.OptionMenu(self.avg_window, subject_var, *subject_options)
        subject_menu.pack()

        # 显示结果的标签
        result_label = tk.Label(self.avg_window, text="")
        result_label.pack()

        def calculate_average():
            subject = subject_var.get()
            with open('data.csv', 'r', encoding="utf-8") as file:
                reader = csv.DictReader(file)
                scores = [int(row[subject]) for row in reader]

            average = sum(scores) / len(scores)
            result_label.config(text=f"{subject}平均值:{average:.2f}")
            result_label.pack(side="bottom")

        # 计算按钮
        calculate_button = tk.Button(self.avg_window, text="计算", command=calculate_average)
        calculate_button.pack(side="top")

    def show_max_score(self):
        self.max_window = tk.Toplevel(self.master)
        self.max_window.title("最高分")

        window_width = 300
        window_height = 150
        screen_width = self.max_window.winfo_screenwidth()
        screen_height = self.max_window.winfo_screenheight()
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2
        self.max_window.geometry(f"{window_width}x{window_height}+{x}+{y}")
        # 下拉列表

        subject_var = tk.StringVar()  # 存储所选科目
        subject_var.set("语文")  # 默认选择语文
        subject_options = ["语文", "数学", "英语"]
        subject_menu = tk.OptionMenu(self.max_window, subject_var, *subject_options)
        subject_menu.pack()

        # 显示结果的标签
        result_label = tk.Label(self.max_window, text="")
        result_label.pack()

        def calculate_max_score():
            subject = subject_var.get()
            with open('data.csv', 'r', encoding="utf-8") as file:
                reader = csv.DictReader(file)
                scores = [int(row[subject]) for row in reader]

            MAX = max(scores)
            result_label.config(text=f"{subject}最高分:{MAX}")
            result_label.pack(side="bottom")

        # 计算按钮
        calculate_button = tk.Button(self.max_window, text="计算", command=calculate_max_score)
        calculate_button.pack(side="top")

    def show_personal_max_min(self):
        self.show_personal_max = tk.Toplevel(self.master)
        self.show_personal_max.title("最高分")
        window_width = 300
        window_height = 150
        screen_width = self.show_personal_max.winfo_screenwidth()
        screen_height = self.show_personal_max.winfo_screenheight()
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2
        self.show_personal_max.geometry(f"{window_width}x{window_height}+{x}+{y}")
        with open('data.csv', 'r', encoding="utf-8") as file:
            reader = csv.DictReader(file)
            names = set(row['姓名'] for row in reader)
        self.name_combobox = Combobox(self.show_personal_max, values=list(names))
        self.name_combobox.pack()
        self.max_score_label = tk.Label(self.show_personal_max, text="")
        self.max_score_label.pack(side="bottom")
        button = tk.Button(self.show_personal_max, text="确定", command=self.show_max_score1)
        label= tk.Label(self.show_personal_max, text="请选择学生")
        label.pack(side="top")
        button.pack(side="top")

    def show_max_score1(self):
        name = self.name_combobox.get()


        with open('data.csv', 'r', encoding="utf-8") as file:
            reader = csv.DictReader(file)
            max_score_subject = None
            max_score = 0
            for row in reader:
                student_name = row['姓名']
                if student_name == name:
                    for subject, score in row.items():
                        if subject != '姓名':
                            score = int(score)
                            if score > max_score:
                                max_score = score
                                max_score_subject = subject



        if max_score_subject:
            self.max_score_label["text"] = f"{max_score_subject}: {max_score}"
        else:
            self.max_score_window = tk.Tk()
            self.window_width = 300
            self.window_height = 200
            self.screen_width = self.max_score_window.winfo_screenwidth()
            self.screen_height = self.max_score_window.winfo_screenheight()
            self.x = (self.screen_width - self.window_width) // 2
            self.y = (self.screen_height - self.window_height) // 2
            self.max_score_window.geometry(f"{self.window_width}x{self.window_height}+{self.x}+{self.y}")
            label = tk.Label(self.max_score_window, text="没有找到成绩")
            label.pack()

大家可以自行去解读需要部分的代码,如果有什么不懂的地方可以交流

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1.学生成绩管理系统分为三个用户角色,登录界面可以选择三种不同的角色进行登录系统 2.管理员角色登录系统可以有以下功能: 管理考试信息:可以对考试批次信息进行增删改查操作 管理教师信息:可以对教师个人信息进行增删改查操作,包括教师的姓名/所属班级/生日/性别/登录密码/家庭住址身份证等信息 管理班级信息:可以对班级名称信息进行增删改查操作 管理学生信息:可以对学生个人信息进行增删改查操作,包括教师的姓名/所属班级/生日/性别/登录密码/家庭住址身份证等信息 查看学生成绩:可以查看学生的所属班级,考试批次,姓名,科目,成绩信息 管理课程信息:可以添加课程,也可以从编辑删除操作 管理专业信息:可以添加专业,也可以从编辑删除操作 注销退出系统 3.教师登录系统可以拥有以下功能: 教师个人信息:可以查看自己的个人信息,可以编辑修改自己的信息 教师录入成绩:可以录入学生的成绩:包含学生的所属班级,考试批次,姓名,科目,成绩,可以编辑删除操作 教师查看班级:可以查看现在的班级情况 教师查看专业:可以查看现在的专业情况 修改密码:可以修改个人的登录密码功能 注销退出系统 4.学生登录系统可以拥有以下功能: 学生个人信息:可以查看自己的个人信息,可以编辑自己的信息 学生查看成绩:可以查看学生的成绩,包含班级,考试批次,姓名成绩等属性,也可以按照考试批次快速检索学生信息 学生成绩排名:可以按照成绩高低排名进行查看 学生选择课程:可以添加学生自己的选课信息,可以编辑删除操作 修改密码:可以修改个人的登录密码功能 注销退出系统 备注:系统使用django+mysql进行开发,前端界面大方美观

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值