ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python+Django构建大学生请假管理系统全解析

Python+Django构建大学生请假管理系统全解析 你肯定在学生时代被请假流程坑过纸质假条要提前打印、找辅导员签字、遇上老师开会还得跑第二趟最后假条去哪了也无从查证。做这个基于PythonDjango的大学生请假管理系统就是想用一套Web应用把“学生申请、辅导员审批、记录留痕”整个闭环搬到线上让请假这种高频又琐碎的事务不再靠喊和跑。这套系统的核心价值很清楚学生端能在线提交假条、实时查看审批进度管理端能批量处理待办、按班级或日期筛选记录所有审批操作都写进数据库期末查考勤、对课时都有据可依。技术栈选了Python和Django原因也很直接——Django自带Admin后台、ORM、表单处理和用户认证一个框架把权限、数据库、页面渲染全部兜住非常适合课程设计、毕业设计以及新手练手的第一套Web项目。适合谁来参考正在学Python想做Web方向的人被前后端联调折磨的初学者以及需要一个既能答辩演示、又能实际跑通的项目的在校生。这篇文章我会从项目结构、数据库设计、核心业务逻辑到部署注意事项完整过一遍不说空话代码直接可抄。1. 整体设计与技术选型思路1.1 为什么是Django而不是Flask或FastAPI选技术栈时我一般只考虑三件事项目周期多长、需不需要现成的管理后台、团队里有没有人熟悉这个框架。对大学生请假系统这种场景——有明确的用户角色区分、有审批状态流转、有数据统计需求——Django是性价比最高的选择。它自带的后台Admin能让你在没写一行前端代码的情况下先看到数据长什么样对前期验证模型设计对不对特别有用。Flask轻量、自由但所有组件都要自己拼ORM要另配SQLAlchemy表单验证要装WTForms用户登录要自己写session逻辑。对一个小型管理系统来说这套“自由组合”的成本远高于收益。FastAPI适合高并发接口服务但模板渲染和后台管理并不是它的强项。Django把这些都打包好了MTV架构的天然分层也让代码结构更容易讲清楚——答辩的时候老师问起模块划分你能按模式、视图、模板三条线说得很顺。1.2 项目管理结构按业务拆app而不是按功能拆文件很多新手拿到项目习惯把所有视图写在一个views.py里所有模型放一个models.py。请假系统虽然小但我建议按业务边界拆分成多个app这样后面加功能不会把文件越拖越大。我实际的项目结构是这样的leave_system/ ├── manage.py ├── leave_system/ # 项目配置目录 │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── users/ # 用户模块学生、辅导员、院系领导 │ ├── models.py │ ├── views.py │ ├── urls.py │ └── admin.py ├── leaves/ # 请假业务假条申请与审批 │ ├── models.py │ ├── views.py │ ├── urls.py │ ├── forms.py │ └── admin.py └── templates/ # 共用模板目录 ├── base.html ├── users/ └── leaves/users负责用户认证和角色区分leaves负责请假业务本身。把用户和业务分开是许多项目实战中比较常用的做法因为总有一天你会加入“辅导员管理”“课程管理”之类的功能如果都堆在同一个app里代码就纠缠在一起了。而且不同的app在Django里天然对应不同的数据库表前缀排查数据问题的时候非常直观。2. 从需求出发的数据库模型设计2.1 搞清楚流程再建表请假审批链路的角色与状态设计数据库之前先画一遍业务流程图学生提交假条假条进入待审批队列辅导员可以同意或驳回如果请假时长超过三天可能在很多学校还要经过院系领导审批。不同学校的流程不同但核心角色就是两类学生和审批者辅导员、院系领导。状态流转我建议用整数存而不是字符串因为字符串一旦在代码里改了一个字历史数据就对不上了。我用的是0、1、2、3四个值0表示待审批1表示已通过2表示已驳回3表示已撤销。这样设计的好处是后续做统计时直接按照状态分组不用做文本匹配。2.2 模型字段与关键参数学生信息表Student和请假申请表LeaveRequest是最核心的两个表。Student挂在Django自带的User上做一对一扩展不直接改User表这样可以安全复用Django自带的登录、权限、Session机制。# users/models.py from django.contrib.auth.models import User from django.db import models class Student(models.Model): user models.OneToOneField(User, on_deletemodels.CASCADE, verbose_name关联账户) student_no models.CharField(学号, max_length20, uniqueTrue) name models.CharField(姓名, max_length30) grade models.CharField(年级, max_length10) major models.CharField(专业, max_length50) class_name models.CharField(班级, max_length30) phone models.CharField(手机号, max_length11, blankTrue) def __str__(self): return f{self.student_no} - {self.name}用OneToOneField而不是直接在User上加字段是考虑到后续如果项目扩展成教师端、家长端用户表不需要反复迁移。Django的迁移机制虽然能改字段但每次牵动AUTH_USER_MODEL的修改都容易引发连锁问题。请假表则是整个系统的核心数据载体# leaves/models.py from django.db import models from django.utils import timezone from users.models import Student class LeaveRequest(models.Model): STATUS_CHOICES ( (0, 待审批), (1, 已通过), (2, 已驳回), (3, 已撤销), ) LEAVE_TYPE ( (sick, 病假), (personal, 事假), (other, 其他), ) student models.ForeignKey(Student, on_deletemodels.CASCADE, verbose_name申请人) leave_type models.CharField(请假类型, max_length20, choicesLEAVE_TYPE) start_time models.DateTimeField(开始时间) end_time models.DateTimeField(结束时间) reason models.TextField(请假事由) status models.IntegerField(审批状态, choicesSTATUS_CHOICES, default0) approver models.ForeignKey(Student, on_deletemodels.SET_NULL, nullTrue, blankTrue, related_nameapproved_leaves, verbose_name审批人) reject_reason models.TextField(驳回原因, blankTrue, default) created_at models.DateTimeField(提交时间, defaulttimezone.now) updated_at models.DateTimeField(更新时间, auto_nowTrue) class Meta: ordering [-created_at] def __str__(self): return f{self.student.name} - {self.get_leave_type_display()} - {self.get_status_display()}这里有个细节approver我一开始写成辅导员id直接存整数后来发现想展示“是哪位老师审批的”时还得再去用户表反查很不方便。改成ForeignKey就能通过外键直接拿到审批人的所有信息。related_name一定要单独设置否则和第一行的student外键产生的反向查询名冲突Django会直接报错。start_time和end_time用DateTimeField而不用DateField因为很多请假是半天甚至精确到某个小时比如下午要去医院复查用日期会丢失精度。时间校验逻辑我放在后端的form里而不是前端前端校验只能挡“正常操作”挡不住直接POST请求绕过的情况。2.3 利用Django Admin快速验证数据关联模型写完不要急着去做前端页面先在admin.py里注册一下通过Django自带后台把假数据填进去验证外键关联、choices展示、时间字段显示都没问题再继续。# leaves/admin.py from django.contrib import admin from .models import LeaveRequest admin.register(LeaveRequest) class LeaveRequestAdmin(admin.ModelAdmin): list_display (student, leave_type, start_time, end_time, status, created_at) list_filter (status, leave_type, created_at) search_fields (student__name, student__student_no)这一步不要省。哪怕你方案文档里写了一大堆字段只有真在Admin里点一遍新建、编辑、筛选才会发现哪些字段容易填错、哪些筛选需求没满足。我之前就出现过字段和时间校验都对但管理员想按“请假创建日期”快速筛出某天的数据结果忘记注册list_filter的情况。3. 环境准备与项目初始化的完整流程3.1 一套干净可控的Python环境安装步骤做Django项目第一步就是管好Python环境这一步踩的坑最多。我不建议直接往系统Python里装包因为后面做毕业设计、做课程作业可能还要用到不同版本的依赖全局环境装着装着就乱了。我通常按这套流程来# 1. 安装Python官方下载3.8至3.12任一稳定版本均可 # 安装时务必勾选 Add Python to PATH # 2. 创建虚拟环境在项目目录下执行 python -m venv venv # 3. 激活虚拟环境 venv\Scripts\activate # Windows source venv/bin/activate # macOS / Linux # 4. 安装Django pip install django4.2 # 5. 创建项目 django-admin startproject leave_system # 6. 进入项目目录并创建app cd leave_system python manage.py startapp users python manage.py startapp leaves关于Django版本我建议选4.2而不是最新的5.x。理由是4.2是LTS长期支持版本教程多、第三方组件兼容性好很多生产环境的部署文章也是基于这个版本写的。你遇到报错时能搜到的解决方案会多很多。等你熟悉了再换版本不迟新手阶段没必要为难自己。创建完项目后记得把两个app和模板目录配置进settings.py否则后面一访问就报TemplateDoesNotExist。3.2 settings配置文件里的语言、时区和数据库调整settings.py里有几项必须改不然项目做完了才发现时间全差8小时或中文乱码。其实改动也不大主要是下面这些# settings.py INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, users, leaves, ] LANGUAGE_CODE zh-hans TIME_ZONE Asia/Shanghai USE_I18N True USE_TZ True TEMPLATES [ { BACKEND: django.template.backends.django.DjangoTemplates, DIRS: [BASE_DIR / templates], APP_DIRS: True, OPTIONS: { context_processors: [ django.template.context_processors.request, django.contrib.auth.context_processors.auth, django.contrib.messages.context_processors.messages, ], }, }, ]TIME_ZONE设置成Asia/Shanghai的同时建议把USE_TZ保持为True。前者控制Django展示给用户的时间是上海时区后者控制数据库里存的是带时区信息的UTC时间。如果你把USE_TZ关了存进去的时间就是本地时间将来如果部署到服务器上服务器时区设置不一致所有时间记录都会错位。请假系统涉及“几点到几点”的精确判断时区问题马虎不得。数据库这块开发阶段用默认的SQLite就够了不需要配MySQL。SQLite用文件存储零配置Django开箱即用。唯一要注意的是如果做并发压力测试SQLite会暴露写锁问题但课程设计、答辩演示、日常运行是完全够用的。如果项目要求用MySQL等把所有页面都调通后再迁移Django的ORM让切换数据库的成本变得很低。3.3 数据库迁移并创建超级管理员账户模型定义完成后执行两行迁移命令python manage.py makemigrations python manage.py migratemakemigrations是生成迁移文件migrate是真正把表建进数据库。我会把这两个步骤分开执行而不是图省事连写因为makemigrations阶段如果提示有字段问题你能立刻看到是哪个模型的哪个字段报错排查起来更快。然后创建超级管理员python manage.py createsuperuser这个账号是后续进入Admin后台管理数据的入口密码别用太简单的答辩演示时账号被同级同学顺手改了就尴尬了。创建完成后启动开发服务器访问http://127.0.0.1:8000/admin能看到登录界面就说明项目骨架已经通了。4. 请假业务的核心逻辑与实现4.1 用Django Form做数据校验而非手动解析POST有些初学者喜欢在views里直接request.POST.get(reason)拿数据处理起来不优雅而且容易漏判。Django的Form模块专门干这个事把字段定义和校验规则放在一起视图里只需要几行代码就能完成全部检查。# leaves/forms.py from django import forms from .models import LeaveRequest from datetime import datetime class LeaveForm(forms.ModelForm): start_time forms.DateTimeField( input_formats[%Y-%m-%d %H:%M], widgetforms.DateTimeInput(attrs{type: datetime-local}), label开始时间 ) end_time forms.DateTimeField( input_formats[%Y-%m-%d %H:%M], widgetforms.DateTimeInput(attrs{type: datetime-local}), label结束时间 ) class Meta: model LeaveRequest fields [leave_type, start_time, end_time, reason] def clean(self): cleaned_data super().clean() start_time cleaned_data.get(start_time) end_time cleaned_data.get(end_time) if start_time and end_time: if start_time end_time: self.add_error(end_time, 结束时间必须晚于开始时间) return cleaned_data在clean方法里做跨字段校验这是整个请假表单里最核心的校验位置。结束时间必须晚于开始时间这个规则用单个字段的validators做不了只能在clean里同时拿两个字段做对比。4.2 学生提交假条视图逻辑和登录权限控制提交假条这个视图要同时做两件事验证用户已经登录以及当前登录用户必须关联了学生档案。# leaves/views.py from django.contrib.auth.decorators import login_required from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from django.utils import timezone from .forms import LeaveForm from .models import LeaveRequest from users.models import Student login_required def leave_create(request): try: student request.user.student except Student.DoesNotExist: messages.error(request, 当前账户未绑定学生信息请联系管理员) return redirect(users:profile) if request.method POST: form LeaveForm(request.POST) if form.is_valid(): leave form.save(commitFalse) leave.student_id student.id leave.save() messages.success(request, 请假申请已提交等待辅导员审批) return redirect(leaves:my_list) else: form LeaveForm() return render(request, leaves/leave_form.html, {form: form})登录后用request.user.student这个反向关联拿到学生档案要注意它在数据库里没有记录时会抛出DoesNotExist异常所以一定要用try包裹。另一个更建议的写法是用Django的get_object_or_404但get_object_or_404找不到会返回404而这里用户没有绑定学生信息更合适的表现是引导他去完善资料所以手动处理异常。4.3 辅导员审批假条状态修改与必要的数据校验审批视图的逻辑核心是修改状态字段但要注意几个边界情况。第一只能审批待审批状态的假条已通过或者已驳回的不能再重复审批。第二审批时填写驳回原因应该在通过时留空。login_required def leave_approve(request, leave_id): leave get_object_or_404(LeaveRequest, idleave_id) if leave.status ! 0: messages.warning(request, 该假条已处理不能重复审批) return redirect(leaves:pending_list) if request.method POST: action request.POST.get(action) if action approve: leave.status 1 leave.approver request.user.student leave.reject_reason messages.success(request, 已通过该请假申请) elif action reject: reject_reason request.POST.get(reject_reason, ).strip() if not reject_reason: messages.error(request, 驳回时必须填写驳回原因) return redirect(leaves:approve_page, leave_idleave.id) leave.status 2 leave.approver request.user.student leave.reject_reason reject_reason leave.save() return redirect(leaves:pending_list) return render(request, leaves/approve_form.html, {leave: leave})驳回原因不做强制校验会让辅导员一键误点学生收到驳回通知却不知道哪里有问题这个交互细节在实际使用中很影响体验。Django的messages框架在这里起到临时提示的作用一条消息展示完就消失不需要建表存储。4.4 列表页展示与查询筛选列表页是整个系统使用频率最高的页面尤其对学生来说“我的请假记录”需要包含历史状态展示。我建议用ListView配合模板来实现这样分页也顺手做了。from django.views.generic import ListView class MyLeaveListView(ListView): model LeaveRequest template_name leaves/my_list.html context_object_name leaves paginate_by 10 def get_queryset(self): return LeaveRequest.objects.filter( studentself.request.user.student ).select_related(approver)这里有个性能细节select_related会在查询请假记录的同时把关联的审批人信息一起查出来避免每显示一条假条就额外执行一次数据库查询。数据量小时感觉不出来但几百条数据后页面加载速度差异会非常明显。这也算是个容易被忽略但很实用的习惯。4.5 权限控制与页面访问范围请假系统里有两类角色学生和辅导员。Django自带的权限系统可以支持更细粒度的控制但为了简单明了我在视图层级直接判断登录用户有没有对应的学生档案。如果用户既有学生档案又具备辅导员身份可以用Django的UserPassesTestMixin做一个判断函数这样代码可读性更高。另一种常见的需求是实现辅导员只能看到自己班级学生的请假记录。这种场景就要在get_queryset里按当前登录用户的班级过滤class PendingLeaveListView(ListView): template_name leaves/pending_list.html context_object_name leaves paginate_by 20 def get_queryset(self): current_student self.request.user.student return LeaveRequest.objects.filter( status0, student__class_namecurrent_student.class_name ).select_related(student)这里通过双下划线student__class_name直接在ORM层面完成跨表过滤效率比把所有假条拿到Python内存里再筛高得多。Django的ORM查询语法越用越觉得顺手遇到复杂的筛选条件先在ORM层面想能不能解决再考虑写原生SQL。5. URL路由与模板渲染细节5.1 路由设计用include拆分到app内部项目根路由和子路由分离这是Django的标准做法项目大了以后能少踩很多坑# leave_system/urls.py from django.contrib import admin from django.urls import path, include urlpatterns [ path(admin/, admin.site.urls), path(users/, include(users.urls)), path(leaves/, include(leaves.urls)), ]子路由按动作拆明细粒度命名空间用app_name隔离这样模板里用reverse也能准确定位# leaves/urls.py from django.urls import path from . import views app_name leaves urlpatterns [ path(create/, views.leave_create, namecreate), path(my/, views.MyLeaveListView.as_view(), namemy_list), path(pending/, views.PendingLeaveListView.as_view(), namepending_list), path(int:leave_id/approve/, views.leave_approve, nameapprove_page), ]5.2 模板继承与表单渲染少写重复代码模板通过base.html方式做套壳每个页面只需要覆盖content块。表单字段用Django自动渲染把错误信息逐条展示出来!-- templates/leaves/leave_form.html -- {% extends base.html %} {% block content %} div classcontainer mt-4 h2提交请假申请/h2 form methodpost {% csrf_token %} {% for field in form %} div classmb-3 {{ field.label_tag }} {{ field }} {% if field.errors %} div classtext-danger{{ field.errors }}/div {% endif %} /div {% endfor %} button typesubmit classbtn btn-primary提交申请/button /form /div {% endblock %}{% csrf_token %}一定不能漏。Django的CSRF防护默认开启POST请求不带这个令牌会直接返回403新手第一次遇到会一脸懵。模板里的表单只要用了POST方法这个标签就是必须的。列表页的展示要注意状态值的映射直接在模板里写数字判断会导致页面逻辑和数字耦合。更优雅的方式是在模型里定义get_status_display方法模板中直接调用td{{ leave.get_status_display }}/td td{{ leave.leave_type }}/td td{{ leave.start_time|date:Y-m-d H:i }}/td时间字段原生会输出类似2024-03-08T10:00:0008:00的格式为了界面和谐加上date过滤器手动格式化这个细节很多新手开发时容易漏掉直到答辩演示时被老师问到“这个时间怎么和预想的不一样”才想起来处理。5.3 登录、退出与注册页面的快速实现Django自带的认证视图能省一大半事登录和退出不用自己写视图逻辑# users/urls.py from django.urls import path from django.contrib.auth import views as auth_views from . import views app_name users urlpatterns [ path(login/, auth_views.LoginView.as_view(template_nameusers/login.html), namelogin), path(logout/, auth_views.LogoutView.as_view(), namelogout), path(register/, views.register, nameregister), ]登录页模板里只需要一个form标签action指向当前页面URL用户名和密码两个输入框就行。Django的LoginView会在验证失败时自动把错误信息传到模板的form.errors里。注册视图要处理的事情稍微多一点验证两次密码一致、创建User对象、创建Student档案。这里有一个容易踩的坑密码必须用create_user而不是直接User.objects.create因为前者会调用set_password对密码做哈希后者存的是明文安全性极差。6. 项目上线前必须处理的细节6.1 settings里容易被忽略的部署开关很多人在本地开发得挺顺畅一到部署就各种白屏十有八九是settings里的Debug没有关或者ALLOWED_HOSTS没有配置。部署环境下的settings至少要做这几处调整DEBUG False ALLOWED_HOSTS [你的域名或服务器IP] STATIC_ROOT BASE_DIR / staticfiles STATICFILES_DIRS [BASE_DIR / static] # 安全相关 SESSION_COOKIE_SECURE True CSRF_COOKIE_SECURE True SECURE_SSL_REDIRECT True调试模式关掉是必须的否则一报错就回显完整堆栈等于把服务器目录结构和代码路径暴露给访问者。本地开发也可以关掉再跑一遍提前把静态文件加载问题、跨域问题全部暴露出来。6.2 collectstatic与静态文件路径注意事项Django开发服务器会自动帮你处理静态文件请求所以本地基本不会遇到静态文件404的问题。但部署环境不一样需要先把所有app里的静态文件收集到一个统一目录再交给Nginx这类Web服务器处理python manage.py collectstatic执行完这步之后检查一下staticfiles目录里是不是包含了bootstrap、custom.css这些你引用的文件。如果没有多半是STATICFILES_DIRS配漏了或者你的静态文件放在了某个app内部但没被扫描到。6.3 备份与日常数据保存不要只在本地留着数据库文件开发过程中跑一次迁移、改一个字段数据库结构都可能变化。建议每次做完一个小功能就用Django的dumpdata做一次逻辑备份python manage.py dumpdata --indent 4 backup.json恢复的时候用loaddata。对SQLite这种文件型数据库直接拷贝db.sqlite3文件做快照也行但dumpdata的优势是可读且与数据库类型无关后面换MySQL也能用它做数据迁移。6.4 用Gunicorn加Nginx跑一个能长期运行的服务开发服务器runserver只适合本地调试它单线程、性能弱直接挂到服务器上碰到并发请求分分钟卡死。生产环境常见组合是Gunicorn跑Django应用Nginx负责转发请求和处理静态文件pip install gunicorn gunicorn leave_system.wsgi:application --bind 0.0.0.0:8000 --workers 3Nginx配置里要把location /静态文件目录和location /动态请求分开动态请求用proxy_pass转发到127.0.0.1:8000静态文件直接用alias指向本地的staticfiles目录。这个配置熟悉一遍之后以后部署别的Django项目都一个套路。7. 常见问题与排查技巧实录7.1 高频问题速查表把我在开发过程中遇到的高频问题整理成了一张速查表希望能帮你省下反复搜索的时间现象常见原因解决办法提交表单后403错误模板中未加{% csrf_token %}在form标签内部添加该模板标签登录后访问某些页面仍跳回登录页视图函数缺少login_required装饰器给需要登录的视图加上装饰器或在URL配置里控制时间和本地时间差8小时settings中TIME_ZONE未设置或USE_TZ设置不当设置TIME_ZONEAsia/Shanghai并检查USE_TZ语义反向查询名冲突报错两个ForeignKey指向同一模型未设置related_name为每个外键指定不同的related_namemakemigrations检测不到模型变化app未注册到INSTALLED_APPS确认settings里的INSTALLED_APPS包含对应app部署后静态文件全部404未执行collectstatic或STATIC_ROOT未配置执行python manage.py collectstatic并检查Nginx配置页面显示数据库异常修改模型后忘记migrate执行makemigrations和migrate确认迁移文件已生成7.2 时间筛选的一个隐藏坑请假记录里常要按日期范围筛选比如查这个月一共请了多少人次我一开始用的写法是start_time__date大于等于某个日期条件多了以后SQL查询特别慢。后来发现更高效的方式是直接用时间范围组合from django.utils import timezone from datetime import timedelta start_of_month timezone.now().replace(day1, hour0, minute0, second0, microsecond0) month_leaves LeaveRequest.objects.filter( start_time__gtestart_of_month, status1 ).values(student__name).annotate(totalCount(id))用gte大于等于而不是date字段过滤能让数据库直接走索引数据量上来后性能差距很明显。这种写法也方便后续扩展成“本周”“本学期”等各种常用时间范围。7.3 在组队开发时如何管理依赖和环境如果是几个人一起做课程设计最痛苦的事情就是A电脑上能跑B电脑上报错。这里推荐用requirements.txt把依赖固定住并且把虚拟环境目录排除在版本管理之外pip freeze requirements.txt对方拿到的代码后只需python -m venv venv venv\Scripts\activate pip install -r requirements.txt python manage.py migrate python manage.py runserver如果某个人改了模型他必须生成迁移文件并提交到版本库而不是只提交修改后的models.py。这个步骤经常被新手忽略结果每次同步代码都要重新删库挺浪费时间的。好的协作流程是改模型→makemigrations→migrate→把迁移文件一起提交这样团队成员pull代码后直接migrate就能对齐数据库结构。8. 从开发到答辩的完整复盘与个人体会开发这套请假系统对我而言最大的收获不是学会了写Django而是体会到了“业务流程驱动代码结构”这回事。一开始我的想法很简单建两张表、写几个页面、能登录能提交就行。但真正开始做了才发现光一个“请假时长超过三天需要额外审批”的规则就牵扯到字段设计、审批队列筛选、状态流转、通知展示一系列改动。业务规则每多一条代码的复杂度和需要测试的场景就多一圈。我个人在实际操作中的体会是项目做出来的样貌很大程度上取决于最开始的需求梳理。哪怕你拿到的只是一个课程设计题目也别急着建项目先把角色、流程、状态全列出来比多写一百行代码管用得多。我在这套系统里把用户角色和业务模块拆成了两个app答辩时老师问“为什么这样分”这个理由本身就体现出了对项目整体结构的思考深度。最后再分享一个有效的小技巧在做完每个功能后用Django的dumpdata备份一次数据。你别小看这个习惯演示现场最怕的就是数据库出了状况导致页面报错。有了备份最多花两分钟恢复不至于在老师面前对着500服务器错误发呆。如果后续还有余力可以在现有基础上增加数据可视化的统计页面给辅导员展示班级请假趋势、用Django的信号机制在请假审批通过后自动发送通知。基础已经打牢了往上叠新功能的路很顺畅。这个项目固然谈不上宏大但它帮你把Python、Django、数据库设计、前端模板、部署上线整条Web开发链路完整过了一遍这种全流程的掌控感本身就很有价值。
返回列表