ARTICLE DETAIL

资讯详情

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

Django实战:从零搭建多功能校园网站毕设项目全解析

Django实战:从零搭建多功能校园网站毕设项目全解析 1. 这个毕设到底在做什么1.1 为什么选Django做校园网站每年计算机专业的毕业设计题目里校园网站、校园管理系统都是高频选题很多同学第一反应是“太老套了”但实际上这个题目放到今天依然值得做关键在于你用什么技术、做出了什么层次。我自己的经验是校园网站非常适合作为Django的入门到综合实战项目因为它业务边界清晰数据模型容易理解功能模块可多可少伸展空间大想拿高分或者想混学分都能找到适合自己的实现路径。选Django而不是Flask、Spring Boot或原生PHP核心原因有三点第一Django的“全家桶”特性特别契合毕设周期。一个项目从零开始到能演示最怕的是自己拼轮子。Django自带ORM、Admin后台、认证系统、表单处理、模板引擎光这五样就能砍掉一大半重复工作。校园网站需要的用户登录、数据管理、页面展示几乎都被它覆盖了你只需要把精力放在业务逻辑上。第二Django的ORM让你跟数据库打交道的方式接近“说人话”。写一个class Student(models.Model)然后同步数据库增删改查都是Python方法调用不需要手写一堆SQL。对做毕设的同学来说这意味着即使你MySQL学得一般也完全能把数据这块扛下来。第三Django的社区资料极其丰富搜“Django项目实战”能找到大量案例遇到报错基本都有现成答案。别的框架遇到冷门报错可能卡你两天Django顶多卡你两小时。有人可能会问那用AI Agent开发Django是不是更快确实现在用AI辅助写代码的效率比以前高很多但AI只能帮你生成代码片段项目结构、数据表设计、业务边界这些核心决策还是得自己拿捏。所以这篇文章我不会只贴代码而是把“为什么这么做”讲清楚这样你答辩的时候也不心虚。1.2 多功能校园网站的功能地图“多功能”这三个字是毕设题目的核心亮点也是评分老师最看重的地方。一个只有新闻列表的网站不叫多功能顶多算个静态页面。我建议把功能拆成六个核心模块每个模块都能独立演示相互之间又有数据关联这样整套系统看起来才“丰满”。模块核心功能涉及的数据表新闻公告校园新闻、通知公告的发布与展示Article课程查询按院系、教师、教室查询课表Course, Teacher社团活动社团介绍、活动报名、活动回顾Club, Activity失物招领发布失物/招领信息、认领申请LostFound二手集市发布闲置物品、留言询价SecondHandItem留言反馈用户留言、管理员回复Message这六个模块覆盖了信息发布、查询检索、用户交互、管理后台四大类典型场景基本把Web开发的主要技能点都串起来了。而且每个模块的难度递进新闻公告最基础适合先练手课程查询涉及多表关联查询适合练ORM功底失物招领和二手集市涉及用户交互状态流转适合练表单和权限控制社团活动报名则能体现你对“一对多关系”的理解。功能模块不一定要全部做完但至少要保证其中两三个模块是完整闭环的——也就是从用户操作到数据落库再到管理端处理整条链路走得通。这样演示的时候老师问什么你都能接得住比做了五个半成品要强得多。2. 从零开始搭Django项目环境与骨架2.1 环境准备与安装开始之前先把环境理清楚。我推荐 Python 3.10 以上版本搭配 Django 4.2 LTS长期支持版。这个组合的好处是Python 3.10 以上语法新Django 4.2 稳定且文档完善网上教程最多。不要一上来就装 Django 5.0 最新版毕设阶段求稳不求新LTS版本能避免很多兼容性问题。安装步骤很简单但有几个细节值得注意。强烈建议用虚拟环境不要直接把Django装进全局Python里。很多同学后面项目跑不起来就是全局环境里装了一堆乱七八糟的包版本互相冲突。命令如下# 创建并激活虚拟环境Windows python -m venv venv venv\Scripts\activate # 创建并激活虚拟环境macOS/Linux python3 -m venv venv source venv/bin/activate # 安装Django pip install django4.2.*装完之后验证一下python -m django --version能正常输出版本号就说明环境没问题。这里补充一个常见坑有些人电脑上同时装了Python2和Python3输python和pip可能对应不同版本。这时候统一用python -m pip代替直接输pip就能保证装到正确的Python解释器里。2.2 创建项目和appDjango的项目结构以“项目 应用”的方式组织。项目是整个网站的配置容器应用是具体的功能模块。我见过很多新手纠结“该把功能写在哪个文件里”其实就是没搞清楚这层关系。创建项目的命令就一条django-admin startproject campus_site .注意后面那个点.表示在当前目录生成项目文件千万不要漏掉漏掉的话Django会自动创建一个跟项目名同名的子目录目录嵌套就很麻烦。然后创建各个功能app每个app对应一个业务模块。基础模块建议这样拆分python manage.py startapp news python manage.py startapp course python manage.py startapp club python manage.py startapp lostfound python manage.py startapp marketplace python manage.py startapp message为什么要把功能拆分到不同app而不是全部写在一个app里这是Django设计哲学里最重要的一个理念松耦合。各个app通过URL路由和模板组装在一起但业务代码互不干扰。好处是某个模块出bug了不影响其他模块运行后期想删掉某个功能直接撤掉对应app就行答辩时你说“我用了模块化设计”老师一听就觉得你有工程意识。创建完app之后记得去campus_site/settings.py的INSTALLED_APPS里把每个app都注册进去。这一步很多人容易忘注册完之后python manage.py runserver才能识别到新增的app。2.3 关键配置项说明settings.py是整个项目的“总控台”我挑几个对毕设项目最关键的配置说一下。数据库配置默认是SQLite对毕设来说完全够用文件型数据库零配置直接把整个数据库备份走就能带走项目。如果你用的是MySQL需要在DATABASES里配置host、port、user、password还要先装mysqlclient或pymysql驱动。我个人的建议是毕设优先用SQLite省去数据库服务安装这一堆事把精力放在业务上。如果导师强烈要求MySQL再切也不迟Django的ORM屏蔽了底层差异迁移一下数据就行。静态文件配置校园网站肯定要放图片、CSS、JS这些资源。开发阶段直接用默认配置就行但部署到服务器上之前必须把STATIC_ROOT和STATIC_URL配好。否则图片显示不出来答辩现场非常尴尬。语言与时区默认配置是英语和UTC咱们直接改成中文和北京时间LANGUAGE_CODE zh-hans TIME_ZONE Asia/Shanghai USE_TZ True这样Django Admin后台会自动变成中文界面管理端的体验一下子提升一个档次。还有一个容易被忽略的ALLOWED_HOSTS开发阶段留空就行部署到云服务器后必须把服务器IP或域名填进去不然访问时会报Invalid HTTP_HOST错误。这个坑几乎每个第一次部署的人都会踩。3. 数据模型设计把校园业务变成ORM对象3.1 各功能模块的表结构设计数据模型是整个项目的基石表结构设计得好后面所有功能写起来都顺。我的设计原则是先画业务关系图再写代码。不要一上来就敲models.py先想清楚每个模块有哪些数据、数据之间是什么关系。以新闻公告模块为例# news/models.py from django.db import models from django.contrib.auth.models import User class Category(models.Model): name models.CharField(分类名称, max_length50) created_at models.DateTimeField(auto_now_addTrue) def __str__(self): return self.name class Article(models.Model): title models.CharField(标题, max_length200) content models.TextField(正文) category models.ForeignKey(Category, on_deletemodels.CASCADE, verbose_name分类) author models.ForeignKey(User, on_deletemodels.SET_NULL, nullTrue, verbose_name作者) is_published models.BooleanField(是否发布, defaultFalse) views models.PositiveIntegerField(浏览量, default0) created_at models.DateTimeField(发布时间, auto_now_addTrue) updated_at models.DateTimeField(更新时间, auto_nowTrue) def __str__(self): return self.title这里面有两个细节特别值得讲。第一个是ForeignKey的外键字段它表示了“一篇新闻属于一个分类作者是一个用户”这种关系。on_delete参数决定了当被关联的对象被删除时当前对象该怎么办。CASCADE意思是分类删掉它下面的文章一起删SET_NULL意思是作者被删了文章保留但作者置空。这个参数必须显式写不写的话Django会强制你选一个这也是新版本的一个硬性要求。第二个是is_published这个布尔字段。很多人写新闻模块直接就查所有文章然后渲染出来结果不想展示的草稿也显示在首页了。加一个状态字段发布前置为False管理员在后台勾选发布后置为True前端只查is_publishedTrue的数据这套逻辑非常实用。课程模块的表结构稍微复杂一点涉及多表关联# course/models.py class Teacher(models.Model): name models.CharField(姓名, max_length50) title models.CharField(职称, max_length50, blankTrue) department models.CharField(所属院系, max_length100) def __str__(self): return self.name class Course(models.Model): name models.CharField(课程名, max_length100) code models.CharField(课程编号, max_length20, uniqueTrue) teacher models.ManyToManyField(Teacher, verbose_name授课教师) credit models.FloatField(学分) classroom models.CharField(教室, max_length50) day_of_week models.IntegerField(星期几, choices[(i, str(i)) for i in range(1, 8)]) start_section models.IntegerField(开始节次) end_section models.IntegerField(结束节次) def __str__(self): return self.name这里课程和教师是ManyToManyField多对多关系因为现实中一门课可能由多个老师合上一个老师也带多门课。ORM会自动生成一张中间关联表管理这种关系你只需要在代码层面声明迁移的时候Django会帮你处理好。3.2 用admin后台快速验证Django自带的后台管理是毕设里性价比最高的功能不需要额外写一行代码就能获得一个完整的增删改查界面。你只需要在admin.py里做简单注册# news/admin.py from django.contrib import admin from .models import Article, Category admin.register(Article) class ArticleAdmin(admin.ModelAdmin): list_display (title, category, author, is_published, created_at) list_filter (is_published, category) search_fields (title, content) list_editable (is_published,) date_hierarchy created_at这些配置项非常有用list_display决定后台列表页显示哪些列list_filter是右侧的筛选器search_fields是搜索框list_editable可以让你在列表页直接修改某个字段比如下拉切发布状态date_hierarchy则在页面顶部生成一个按日期筛选的时间轴。后台配置好之后先用python manage.py createsuperuser创建管理员账号然后启动服务访问http://127.0.0.1:8000/admin就能看到后台了。我强烈建议每个模块的model都注册进admin。这样开发期间你在后台模拟各种数据比自己写SQL或者写脚本灌数据快得多。更重要的是答辩时给老师演示“我用管理后台维护内容”这个场景非常直观。3.3 查询与删除对象的正确姿势Django的ORM查询几乎覆盖了毕设所有场景我把最常用的一套模式整理出来# 查询所有已发布的文章 Article.objects.filter(is_publishedTrue) # 按分类筛选且按时间倒序 Article.objects.filter(category__name校园新闻).order_by(-created_at) # 获取某篇文章的详情不存在则返回404 from django.shortcuts import get_object_or_404 article get_object_or_404(Article, pkarticle_id) # 统计浏览量并更新 article.views 1 article.save(update_fields[views])这里重点说一下删除对象的几种方式和它们的区别。第一种是最常用的先查出来再删。article Article.objects.get(pkarticle_id) article.delete()第二种是直接通过查询集批量删除Article.objects.filter(category__name旧分类).delete()它能把所有符合条件的文章一次性删除效率很高但风险也大。我不建议在正式项目里这么干万一条件写错了数据全没了连找回的机会都没有。安全做法是先从管理后台或写一个管理命令把符合条件的记录列出来确认无误后再执行删除。第三种是软删除方案这个非常适合带用户互动的校园网站class Article(models.Model): ... is_active models.BooleanField(defaultTrue) # 所谓“删除”其实只是把状态置为False article.is_active False article.save()硬删除会把数据记录从表里物理移除而软删除只是标记一条记录“不可见”。对于失物招领、二手集市这种业务用户可能会后悔、管理员可能要复查软删除的价值就体现出来了。我的建议是普通数据直接硬删除没问题但涉及用户产生的内容优先做软删除。还有一个小技巧在模型里自定义删除方法统一处理删除逻辑这样任何地方调用都不会遗漏关联状态。def soft_delete(self): self.is_active False self.save()4. 视图、模板与路由让网页真正动起来4.1 视图函数的编写套路模型建好了接下来要处理的是“用户请求怎么来、数据怎么传、页面怎么返回”这一段流程。Django里最标准的写法是函数视图FBV虽然也有类视图CBV但我的建议是毕设阶段把函数视图吃透效果最好因为逻辑直观调试方便。以新闻列表和详情页为例# news/views.py from django.shortcuts import render, get_object_or_404 from .models import Article, Category def article_list(request): # 读取查询参数中的分类ID没有则为None category_id request.GET.get(category) articles Article.objects.filter(is_publishedTrue) if category_id: articles articles.filter(category_idcategory_id) # 读取查询参数中的搜索关键词 keyword request.GET.get(q) if keyword: articles articles.filter(title__icontainskeyword) # 排序置顶文章优先按时间倒序 articles articles.order_by(-created_at) return render(request, news/article_list.html, { articles: articles[:20], categories: Category.objects.all(), current_category: category_id, keyword: keyword, }) def article_detail(request, article_id): article get_object_or_404(Article, pkarticle_id, is_publishedTrue) article.views 1 article.save(update_fields[views]) return render(request, news/article_detail.html, {article: article})这里要重点讲request.GET.get这个方法。校园网站搜索场景非常多——按关键词搜新闻、按名称搜社团、按课程号搜课表全部都是同一个套路。通过URL参数传查询条件视图里接收参数利用ORM的链式筛选逐渐缩小结果集最后模板渲染。这种模式的代码复用率非常高把一套写熟其他模块依葫芦画瓢即可。4.2 模板继承与页面复用写校园网站时各个页面有大量重复部分顶部导航、底部版权信息、侧边栏。如果不做任何处理每个页面都要复制粘贴一大段HTML不仅维护麻烦而且容易出错。Django模板系统最核心的机制就是模板继承。先建立一个基础模板templates/base.html!DOCTYPE html html langzh-hans head meta charsetUTF-8 title{% block title %}校园网站{% endblock %}/title link relstylesheet href{% static css/base.css %} {% block extra_css %}{% endblock %} /head body header classsite-header nav a href{% url home %}首页/a a href{% url news:list %}新闻公告/a a href{% url course:list %}课程查询/a a href{% url club:list %}社团活动/a a href{% url lostfound:list %}失物招领/a a href{% url marketplace:list %}二手集市/a /nav div classuser-area {% if user.is_authenticated %} span欢迎{{ user.username }}/span a href{% url logout %}退出/a {% else %} a href{% url login %}登录/a a href{% url register %}注册/a {% endif %} /div /header main classcontent {% block content %}{% endblock %} /main footer classsite-footer p校园网站 · 计算机毕业设计作品/p /footer {% block extra_js %}{% endblock %} /body /html然后业务页面只需要专注自己的内容{% extends base.html %} {% block title %}新闻列表 - 校园网站{% endblock %} {% block content %} h1新闻公告/h1 !-- 新闻列表循环 -- {% for article in articles %} div classarticle-item h2a href{% url news:detail article.id %}{{ article.title }}/a/h2 p{{ article.created_at|date:Y-m-d }} · {{ article.category.name }}/p p{{ article.content|truncatechars:100 }}/p /div {% empty %} p暂无新闻请待管理员发布内容。/p {% endfor %} {% endblock %}模板继承的威力在于底部的版权信息要改只改base.html一处全站瞬间生效导航栏要加个“校园地图”链接也只改base.html。这在项目后期调整页面整体样式时太省事了我第一次做项目的时候不认识这个机制每个页面单独改改得脑袋大。模板过滤器也值得提一下。|date:Y-m-d把日期的显示格式化|truncatechars:100截断字符串为100个字符。Django自带二十多个过滤器都是这种竖直管道符语法能让模板的表达能力强很多。4.3 URL路由规划路由的作用是告诉Django“哪个URL对应哪个视图”。校园网站页面多把路由规划清晰非常重要。我推荐在项目级主路由里用include把不同app的URL分离开再给每个app单独建一个urls.py。# campus_site/urls.py from django.contrib import admin from django.urls import path, include from django.views.generic import TemplateView urlpatterns [ path(admin/, admin.site.urls), path(, TemplateView.as_view(template_namehome.html), namehome), path(news/, include(news.urls)), path(course/, include(course.urls)), path(club/, include(club.urls)), path(lostfound/, include(lostfound.urls)), path(market/, include(marketplace.urls)), path(message/, include(message.urls)), path(accounts/, include(django.contrib.auth.urls)), ]# news/urls.py from django.urls import path from . import views app_name news urlpatterns [ path(, views.article_list, namelist), path(category/int:category_id/, views.article_list, namelist_by_category), path(int:article_id/, views.article_detail, namedetail), ]两个细节要记住。第一app_name news给这个app的路由命名空间这样模板里写{% url news:detail article.id %}就不会跟其他app的detail路由名称冲突。第二路径转换器int:article_id会从URL里提取整数型参数传给视图的article_id参数这个语法非常直观。首页的写法我用的是TemplateView直接渲染模板不需要额外写视图函数这种“纯静态页面直接用类视图”的偷懒方式在页头页脚、About页面等地方非常实用。5. 用户认证与权限控制5.1 Django自带认证系统校园网站几乎所有交互功能都需要用户身份发布失物招领你得知道是谁发的报名社团要知道谁报了名二手集市留言要知道联系谁。如果要求你自己从零实现会话管理、密码加密、登录状态保持估计能写一个月。Django内置认证系统把这些全包了。django.contrib.auth提供了User模型、登录、登出、密码哈希等全套能力。默认的User模型包含用户名、密码、邮箱、姓名、权限标志等字段。开发初期直接用就行不需要额外配置。最简单的一套登录注册流程可以这样实现# 在某个app里写 auth_views.py from django.contrib.auth import authenticate, login, logout from django.contrib.auth.decorators import login_required from django.shortcuts import render, redirect def user_login(request): if request.method POST: username request.POST[username] password request.POST[password] user authenticate(request, usernameusername, passwordpassword) if user is not None: login(request, user) return redirect(home) else: # 返回错误信息 return render(request, registration/login.html, {error: 用户名或密码错误}) return render(request, registration/login.html) def user_logout(request): logout(request) return redirect(home) login_required def user_center(request): # 只有登录用户才能访问个人中心 return render(request, user/center.html, {user: request.user})这里的login_required装饰器值得一提它会把未登录用户重定向到登录页登录成功后自动跳回原页面。给视图加一个装饰器等于给整个功能加了一道门禁。用在一个“发布失物招领”的视图上就能确保只有登录用户才能发布。5.2 登录注册与权限校验如果你不想自己写登录页模板还可以直接复用Django自带的认证URLurlpatterns [ path(accounts/, include(django.contrib.auth.urls)), ]这样/accounts/login/、/accounts/logout/、/accounts/password_change/这些URL都被映射好了你只要提供对应的模板文件比如registration/login.html。这个方案真的能省掉不少代码但我个人建议还是自己写一遍登录注册视图更好。不是因为它难而是因为自己写能加深对session、认证流程的理解答辩老师问起来你能讲得头头是道。权限控制方面除了login_required还有一个user_passes_test可以针对特定条件做校验from django.contrib.auth.decorators import user_passes_test def is_admin_user(user): return user.is_superuser or user.groups.filter(name管理员).exists() user_passes_test(is_admin_user) def admin_dashboard(request): return render(request, admin_dashboard.html)校园网站的实操里最常见的权限场景是普通用户可以发信息、报名活动、留言管理员可以删除违规内容、发布公告、管理用户状态。我的建议是把“管理员”作为权限校验的唯一标准不要在代码里到处判断is_superuser或写死用户名否则后期想加个“教学秘书”角色改起来会很难受。正确做法是建一个用户组然后把需要权限管理的用户加到组里。6. 常见问题与排查技巧实录6.1 环境与安装问题问题一django-admin命令找不到。多半是因为虚拟环境没激活或者Python环境变量配置有问题。用python -m django admin试试如果显示“No module named django”说明Django没有安装到当前环境中。问题二pip install django速度极慢或超时。国内网络环境下的常见现象换用国内镜像源即可pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple问题三启动服务时报port 8000 already in use。常见是上一个开发服务器没有关掉。Windows下CtrlC没反应就直接结束终端进程macOS/Linux下用ps aux | grep runserver找到进程号然后kill -9 进程号。不想找进程的话也可以直接换个端口python manage.py runserver 8001。6.2 数据库迁移与查询问题问题四makemigrations之后忘记migrate。这是一个极其常见的新手错误。makemigrations只是生成迁移文件相当于“把改动记录下来”真正生效要执行python manage.py migrate。我见过做了半天模型改动页面一访问就报“no such table: news_article”就是这个原因。问题五ORM查询结果与预期不符。记得检查QuerySet是惰性的只有你在模板里遍历或者强制转换成list()、使用len()的时候才会真正执行数据库查询。调试时可不要直接在Python shell里打印一个QuerySet就认为那是全部结果务必确认字段名拼写无误建议用print(queryset.query)查看实际执行的SQL语句能帮你定位很多问题。问题六删除对象时外键关联报错。这是on_delete设置不当导致的。记得在模型里的每个外键字段上显式设置on_delete参数Django从2.0开始强制要求不设置连迁移都过不去。删除外键时到底用CASCADE还是SET_NULL回到业务逻辑里想用户删了他的留言应该留在表里还是跟着删除留言有价值就保留置空纯附属信息就级联删。6.3 页面渲染与静态文件问题问题七页面没有样式CSS和图片全挂了。开发阶段一定要在settings.py里确保DEBUG True并且staticfilesapp已经在INSTALLED_APPS里。模板头部加载静态文件必须先写{% load static %}只写一次在base模板里就行子模板通过继承就不用再写了。很多同学页面白花花一片多半是漏了这一句。问题八登录后页面跳转不对。Django的LOGIN_REDIRECT_URL这个配置控制登录成功后的默认跳转地址不配置的话默认跳到/accounts/profile/这个页面不存在就会404。统一在settings.py里指定LOGIN_URL /accounts/login/ LOGIN_REDIRECT_URL / LOGOUT_REDIRECT_URL /问题九时区相关的坑。如果你开了USE_TZ True数据库里存的是UTC时间直接datetime.now()拿到的可能不是北京时间。网站上展示时间建议统一在模板里用|date:Y-m-d H:i过滤器Django会自动把UTC时间转换到TIME_ZONE指定的时区。不要在视图里手动拼接时间字符串这套机制会让你少很多麻烦。上面的问题前四个属于“卡住你三天的低级坑”后四个属于“答辩演示当场翻车的重灾区”。我的排查套路一直是这样先看报错信息完整文本不要只看第一行再看URL有没有匹配上用python manage.py shell去手动调用视图函数最后才去翻搜索引擎。这样自己排查出来的问题印象极其深刻下次再遇到几乎不用查资料就能秒答。结尾一些个人经验说实话这类校园网站题目年年有人做能不能拿到好成绩拼的不是功能多么花哨而是整个项目有没有清晰的思路和完整的闭环。我自己的体会是Django这种框架最大的价值在于它把Web开发里最繁琐的公共部分替你处理掉了让你能专注于业务本身。你花一周把基础练熟再把六个模块逐个填进去最后会发现真正写代码的时间并不长大部分时间都花在了调试和打磨细节上。最后分享一个小技巧给项目加一个“数据可视化”页面用统计图表展示新闻浏览量趋势、社团报名人数、每天失物招领新增数量。这不光让系统看起来更高端还能体现你对数据处理的理解。关于图表可以用echarts的CDN文件直接接入后端只需要写一个返回JSON数据的接口前后端分离的程度马上拉开一个档次。祝你把这段开发过程变成一次舒服的实战训练而不是赶工煎熬。毕业答辩顺利。
返回列表