
简介这是一套基于Django框架的在线电影网站系统毕设项目包面向需要完成毕业设计、课程设计或大作业的Python及Web开发学习者覆盖后端开发、数据库管理与Vue前端交互设计。资源共540个文件压缩包大小18.95MB以Vue组件、Python源码、SVG图标、JS逻辑和CSS样式为主同时包含MySQL的SQL脚本、开发说明文档以及安装/运行批处理脚本便于快速部署和二次开发。系统以Django作为后端利用ORM简化数据库操作前端采用Vue实现动态数据更新适合从零搭建或参考典型前后端结合项目的完整实现。目前已有90人学习下载对想系统掌握网站开发全流程、准备毕设答辩或进行工程实训的读者这份含源码、数据库与文档的整合包具有直接参考价值。1. 拿到一套 Django 电影网站系统先看清它到底是什么毕业设计季节最常见的一类课题就是基于 Django 的在线电影网站系统。这类项目看着简单——无非是电影列表、详情页、搜索框加后台管理——但真正动手跑起来、改起来、写到答辩能讲清楚涉及的东西远比想象中多。拿到一个名为 “5p114 基于 Django 的在线电影网站系统 0.zip” 的压缩包打开之后首先需要确认的是这份代码用的是哪个 Django 版本、数据库是 SQLite 还是 MySQL、前端是原生模板还是引了 Bootstrap、有没有第三方登录或支付模块。这些判断决定了你本地能不能直接跑通也决定了你后面改功能时会不会翻车。与其说这是一个“系统”不如说它是一个标准的 Django MVT 架构教学样例Model 定义电影和分类数据View 处理请求和业务逻辑Template 渲染页面。对新手来说这是很好的入门教材对想交一份高质量毕设的从业者来说这套结构也是后续扩展的骨架。这篇文章就顺着这个标题把整个方案的来龙去脉讲清楚——从数据库表设计到核心业务流程从本地跑通到答辩前打磨全部拆开揉碎。2. Django 电影网站系统的整体架构MVT 分层与三张核心数据表2.1 MVT 架构在电影网站里的具体落位Django 的 MVTModel-View-Template和传统 MVC 最大的区别在于Django 自己接管了 Controller 那一层把 URL 分发和请求处理全部并进 View 里。放到电影网站这个场景里MVT 的分工特别清晰Model 层负责定义数据结构。常见的电影网站系统里至少有电影表、分类表、用户表如果需要评论功能还会加评论表。Model 里的字段类型直接决定后续查询和模板渲染的写法比如封面图是用 ImageField 还是 CharField 存 URL这会直接影响部署后图片能不能正常展示。View 层处理用户请求。电影列表页的视图要从数据库里把电影数据取出来传给模板搜索视图要处理 GET 参数并构造查询集详情页视图要根据 URL 里的电影 ID 从数据库取单条记录。视图的逻辑写得干不干净直接决定了答辩时你讲不讲得清楚。Template 层负责页面展示。Django 模板语言里常见的{% for %}循环、{{ object.title }}变量插值、{% url %}反向解析都在这一层。判断一套代码写得是否专业最直接的办法是打开项目的urls.py文件看 URL 分发是否清晰再打开models.py看字段定义是否合理。很多毕设项目把大量逻辑写在视图函数里导致视图长达几百行这种代码后期改起来非常痛苦。2.2 电影表、分类表、用户表字段设计与关系选择在线电影网站的核心是电影数据。绝大多数此类系统的电影表假设叫Movie包含这些字段title电影名称CharFieldmax_length 一般在 100 到 200 之间这个值不用太大但也不能太小中文电影名加副标题很容易超过 50 个字符。cover封面图常见做法是用 ImageField 配合MEDIA_ROOT配置也有直接用 CharField 存外链 URL 的。用 ImageField 意味着你必须配置静态文件和媒体文件的访问路径否则上传的图片在页面上裂开。category外键关联分类表ForeignKey 到Categoryon_deletemodels.CASCADE是最常见的级联删除策略。description电影简介TextField长度不设限。release_date上映日期DateField。rating豆瓣评分或站内评分FloatField注意设置默认值否则老数据会报错。created_at创建时间DateTimeField(auto_now_addTrue)用于后台按时间排序。is_hot或is_recommended布尔字段用于首页热门推荐位。分类表Category通常只有两个字段name和created_at。用户表直接用 Django 自带的User模型不需要额外写用户类。如果系统有收藏功能收藏表是Movie和User的多对多关系通过ManyToManyField实现。这里有一个容易被新手忽略的设计问题删除分类时该分类下的所有电影会被级联删除。如果毕设系统里有真实数据答辩演示时在后台删一个分类整个分类下的电影全部消失这是一个经典翻车场景。更稳妥的做法是on_deletemodels.SET_NULL配合nullTrue, blankTrue让电影在分类被删除后保留下来只是分类变成空。改成这种设计之后前台模板渲染时需要做空值判断{{ movie.category.name }}在分类为空时会显示空白不会报错。2.3 数据库选型SQLite 起步MySQL 备选这类毕设项目默认使用 SQLite因为 Django 的迁移命令在 SQLite 上可以零配置跑通对新手最友好。但如果你打算把系统部署到服务器上演示或者数据集比较大比如上万条电影数据SQLite 的并发写能力会成为瓶颈。常见做法是开发环境用 SQLite提交答辩或部署前切换到 MySQL。切换数据库只需要修改settings.py里的 DATABASES 配置# settings.py 数据库配置片段 DATABASES { default: { ENGINE: django.db.backends.mysql, # 切换为 MySQL 引擎 NAME: movie_db, # 数据库名 USER: root, # 数据库用户 PASSWORD: yourpassword, # 数据库密码 HOST: 127.0.0.1, # 数据库地址 PORT: 3306, # 数据库端口 } }这段配置改动本身不大但有几个连带问题需要处理MySQL 的字符集一定要设为 utf8mb4否则存中文会乱码执行python manage.py migrate之前要先在 MySQL 里创建好movie_db这个库pymysql需要安装并在项目的__init__.py里写入pymysql.install_as_MySQLdb()。这些坑我在后面第 5 章会展开讲总之换数据库不是改一行配置那么简单。3. 本地跑通这套 Django 电影网站环境、依赖与启动命令3.1 Python 环境准备版本选择和虚拟环境隔离在开始运行这个项目之前首先要确认 Python 环境。Django 的版本和 Python 版本有对应关系如果压缩包里的代码是基于 Django 2.2 写的那 Python 3.6 到 3.8 都可以跑如果是 Django 3.2 或 4.xPython 3.8 以上比较稳妥。拿到代码后第一步不是直接跑而是看requirements.txt里锁定的 Django 版本。我一般会先建一个虚拟环境避免把系统 Python 环境搞乱也不要图省事直接装到全局——你在一个项目里装 Django 3.2另一个项目要装 Django 2.2全局环境会直接冲突。用 venv 创建虚拟环境# 进入项目根目录创建虚拟环境 python -m venv venv # 激活虚拟环境Windows venv\Scripts\activate # 激活虚拟环境macOS / Linux source venv/bin/activate激活后命令行前面会出现(venv)前缀这代表你已经进入虚拟环境。这一步没做好的话后面pip install装出来的包会散落到系统目录里项目之间互相污染到时候排查问题根本不知道是哪个版本在起作用。3.2 安装依赖和迁移数据库从 requirements.txt 到 migrate虚拟环境准备好之后安装项目依赖。典型的requirements.txt文件内容至少包含 Django 和 Pillow因为 ImageField 依赖 Pillow 处理图片如果项目用了 Django REST Framework 写 API还会有djangorestframework。执行安装# 安装 requirements.txt 中列出的所有依赖 pip install -r requirements.txt # 如果缺少某个依赖的输出信息单独补装例如 pip install django3.2.25 pip install pillow依赖安装完成后进入项目目录也就是包含manage.py的那一层先看目录结构。一个标准的 Django 项目包含一个外层项目配置目录和一个或多个应用目录。manage.py是 Django 的命令行入口工具所有操作都要通过它来执行。在启动开发服务器之前必须执行数据库迁移命令。Django 会按照应用里models.py的定义创建数据表生成初始的 ORM 映射结构# 生成迁移文件如果项目里已经有迁移文件这步会显示 No changes detected python manage.py makemigrations # 执行迁移把数据表建到数据库里 python manage.py migrate迁移成功后再创建一个后台管理员账号用于登录 Django 自带的 Admin 后台添加电影和管理数据# 创建超级用户按提示输入用户名、邮箱、密码 python manage.py createsuperuser3.3 启动开发服务器runserver 与静态文件问题迁移完成、超级用户创建好之后启动开发服务器python manage.py runserver 127.0.0.1:8000启动后浏览器访问http://127.0.0.1:8000应该能看到电影网站首页。如果首页能打开但页面上的 CSS 样式全丢了这是 Django 静态文件配置的问题。常见原因是settings.py里的STATIC_URL和STATICFILES_DIRS没有配好模板里的{% load static %}和{% static css/style.css %}引用的路径找不到。开发环境下 Django 自带的静态文件服务器可以处理这种情况但需要确认settings.py的DEBUG True以及urls.py里加了静态文件的 URL 映射# urls.py 中添加静态文件访问路径仅限开发环境 from django.conf import settings from django.conf.urls.static import static urlpatterns [ # ... 已有 URL 配置 ] if settings.DEBUG: urlpatterns static(settings.MEDIA_URL, document_rootsettings.MEDIA_ROOT)这段代码的作用是把MEDIA_ROOT目录下的文件映射到MEDIA_URL路径上。如果缺少这段映射电影封面上传后能存到本地磁盘但浏览器访问图片地址会返回 404页面图片全部裂掉。这是电影网站类项目最高频的问题几乎每三个跑这类代码的人就有两个栽在这。4. 核心功能拆解电影列表、搜索、详情页与后台管理的实现路径4.1 电影列表页视图函数如何组装数据电影首页是整个系统的门面通常展示最新上架的电影和热门推荐。列表页的视图函数逻辑不复杂但数据组装的方式直接影响页面性能和代码可读性。典型实现是在应用目录下的views.py里定义一个函数从数据库查询电影数据并渲染模板# views.py 电影列表视图 from django.shortcuts import render from .models import Movie, Category def movie_list(request): # 按创建时间倒序取前 8 部电影作为最新上映板块 latest_movies Movie.objects.all().order_by(-created_at)[:8] # 按 is_hot 字段过滤取热门推荐 hot_movies Movie.objects.filter(is_hotTrue)[:8] # 所有分类用于导航栏展示 categories Category.objects.all() context { latest_movies: latest_movies, hot_movies: hot_movies, categories: categories, } return render(request, movie/list.html, context)这段代码的核心逻辑是三点一是order_by(-created_at)里的负号代表倒序这个 Django 语法很容易忘二是[:8]切片操作会把 QuerySet 转成列表并限制查询条数避免一次查出全表数据三是context字典里的键名必须和模板里的变量名完全一致模板里写{{ latest_movies }}而视图里传的是movies模板就会渲染空列表页面上什么都显示不出来。4.2 搜索功能GET 参数接收与icontains模糊查询搜索是在线电影网站的标配功能。用户在前端输入框提交关键词后Django 视图通过request.GET.get()接收参数再用 ORM 的icontains做模糊查询# views.py 电影搜索视图 from django.db.models import Q def movie_search(request): # 获取搜索关键词默认空字符串 keyword request.GET.get(q, ).strip() movies Movie.objects.all() if keyword: # 在标题和简介两个字段里做不区分大小写的模糊搜索 movies movies.filter( Q(title__icontainskeyword) | Q(description__icontainskeyword) ) context { movies: movies, keyword: keyword, } return render(request, movie/search.html, context)这段代码里值得拆解的细节有几个。request.GET.get(q, )里第二个参数是默认值用户没有输入关键词时返回空字符串不会报MultiValueDictKeyError异常。.strip()是去掉首尾空格防止用户输入空格导致搜不到结果。Q对象允许你用|表示 OR 关系实现标题和简介两个字段同时匹配。如果不加Q对象而直接写成filter(title__icontainskeyword, description__icontainskeyword)那就变成 AND 关系只有标题和简介同时包含关键词的电影才会被搜出来这显然不符合搜索预期。搜索结果的模板里还需要把关键词回填到搜索框里否则用户搜索完刷新页面输入框内容被清空体验很差。模板里的写法是value{{ keyword }}注意这里要用模板变量而不是硬编码。4.3 电影详情页和后台管理单条数据查询与 ModelAdmin 注册详情页的 URL 设计通常带一个动态参数比如/movie/1/里的 1 是电影 ID。Django 的 URL 配置用尖括号捕获参数# urls.py 详情页路由配置 from django.urls import path from . import views urlpatterns [ path(movie/int:movie_id/, views.movie_detail, namemovie_detail), ]对应视图函数接收movie_id参数从数据库取出单条记录# views.py 电影详情视图 from django.shortcuts import render, get_object_or_404 from .models import Movie def movie_detail(request, movie_id): # 根据 ID 获取电影不存在时直接抛 404 movie get_object_or_404(Movie, pkmovie_id) return render(request, movie/detail.html, {movie: movie})get_object_or_404是 Django 里非常实用的一个快捷函数它把try...except的异常处理逻辑压缩成一行取到就返回对象取不到就返回 404 页面。在模板里详情页展示电影标题、封面、分类、评分、简介等信息。如果没有这个函数而直接用Movie.objects.get(pkmovie_id)当电影 ID 不存在时 Django 会抛出DoesNotExist异常用户会看到调试模式的报错页面这在答辩演示时非常尴尬。后台管理部分Django 自带的 Admin 已经够用于毕设演示。只需要在应用的admin.py里注册模型# admin.py 后台注册电影和分类模型 from django.contrib import admin from .models import Movie, Category admin.register(Movie) class MovieAdmin(admin.ModelAdmin): # 后台列表页显示的字段 list_display (title, category, rating, is_hot, created_at) # 可点击跳转到编辑页的字段 list_display_links (title,) # 右侧过滤器按分类筛选 list_filter (category, is_hot) # 搜索框按标题搜索 search_fields (title,) admin.site.register(Category)注册之后访问http://127.0.0.1:8000/admin/用之前创建的超级用户登录就能在后台增删改查电影数据。list_display决定后台列表显示哪些列list_filter在页面右侧生成筛选栏search_fields后台顶部出现搜索框。这些配置在答辩演示时非常有用用它能快速展示系统具备完整的数据管理能力。5. 避坑指南本地运行 Django 电影网站的 5 个高发问题5.1 Python 版本与 Django 版本不匹配导致启动失败现象执行python manage.py runserver直接报语法错误或 ImportError提示某个模块不存在比如django.core.exceptions.ImproperlyConfigured。原因压缩包里的代码基于特定 Django 版本开发而你本地 Python 版本过新或过旧。Django 2.2 不支持 Python 3.9 以上版本Django 4.x 不支持 Python 3.6 及以下版本urlpatterns里的re_path写法在旧版 Django 里也报错。解决打开requirements.txt确认 Django 版本要求。如果要求 Django 2.x新建 Python 3.8 虚拟环境重新安装如果要求 Django 4.x确保 Python 不低于 3.8。装完依赖后执行python -c import django; print(django.get_version())确认版本号再跑runserver。5.2 迁移失败No changes detected或应用目录未注册现象运行python manage.py makemigrations提示项目里没有任何变化但数据库里确实没有数据表后台登录后所有模型都不在。原因settings.py的INSTALLED_APPS列表里没有加入该项目自己的应用名。Django 不扫描未被注册的应用所以makemigrations检测不到任何 Model 变更。解决打开settings.py确认INSTALLED_APPS里包含movie或实际应用名名字从项目目录下哪个文件夹里有models.py和views.py就能判断出来。添加后重新执行python manage.py makemigrations python manage.py migrate执行migrate后可以用python manage.py showmigrations查看所有迁移是否已应用输出里带[X]标记的表示已经成功执行。5.3 静态文件全部丢失页面只有文字没有样式现象浏览器打开首页能显示文字内容但所有 CSS 样式消失图片裂开控制台报大量 404 错误路径全部指向/static/或/media/。原因settings.py里缺少STATICFILES_DIRS配置或者urls.py里没有在DEBUGTrue时挂载静态文件服务。电影封面图走的是MEDIA_URL映射如果MEDIA_ROOT指向的目录不存在Django 会在创建时自动建目录但需要确认目录层级正确。解决项目根目录下创建static文件夹把样式和图片放进去然后在settings.py里添加配置。# settings.py 静态文件配置 import os BASE_DIR os.path.dirname(os.path.dirname(os.path.abspath(__file__))) STATIC_URL /static/ STATICFILES_DIRS [ os.path.join(BASE_DIR, static), ] # 媒体文件电影封面配置 MEDIA_URL /media/ MEDIA_ROOT os.path.join(BASE_DIR, media)配好之后重启runserver再刷新页面样式应该能正常加载。5.4 封面图上传成功但页面显示 404现象后台添加电影并成功上传封面但前台页面图片地址访问时返回 404文件已经存在本地目录里。原因模板里引用的图片路径不是MEDIA_URL 图片文件名而是直接写死了/media/xxx.jpg或者漏掉了 Django 模板语法img src{{ movie.cover.url }} alt{{ movie.title }}{{ movie.cover.url }}这个模板变量会调用 ImageField 的url属性自动拼接出完整访问路径。如果模板里写的是{{ movie.cover }}渲染出来的只是一个文件名不带/media/前缀浏览器自然访问不到。解决检查模板里所有图片标签把封面路径全改为{{ movie.cover.url }}确认urls.py里已经挂载了静态文件映射。5.5 搜索页面中文关键词搜不出结果现象输入中文关键词搜索时列表为空但后台明明有数据换成英文关键词却能搜出来。原因SQLite 的icontains对中文支持没有问题但如果前端模板的表单没有指定methodget搜索请求就变成 POST视图里request.GET.get(q)永远取不到值。另一个常见原因是搜索逻辑里用了精确匹配而不是icontains把等值查询写成filter(titlekeyword)就会导致只能搜完全一致的电影名。解决检查前端表单标签是否写了methodget并把action指向搜索路由再看视图里是不是用了icontains模糊查询。最后在视图函数里加一句打印调试print(f搜索关键词: {keyword}, 结果数量: {movies.count()})在runserver的控制台就能看到实际搜索参数和查询结果快速定位问题出在前端还是后端。6. 答辩前把系统打磨得更完整用 Data Migration 填充数据与演示要点毕设演示最怕的不是功能不完整而是页面上空荡荡没有数据。评委看到空白页面第一反应是系统没做出来。所以答辩前一定要给数据库填充足够的电影数据至少要有 20 部以上真实电影信息分类不少于 5 个热门推荐位要能看到明显的视觉效果。填充数据最常见的做法是手动在 Admin 后台录入但效率太低。更专业的做法是用 Django 的 Data Migration 机制写一个数据迁移脚本让数据随数据库迁移自动生成。创建一个空的迁移文件python manage.py makemigrations --empty movie然后编辑生成的迁移文件在里面添加数据写入逻辑# migrations/0002_seed_data.py 数据填充迁移 from django.db import migrations def seed_movies(apps, schema_editor): Movie apps.get_model(movie, Movie) Category apps.get_model(movie, Category) # 先创建分类 categories [动作, 科幻, 喜剧, 爱情, 动画] category_objs [Category.objects.create(namename) for name in categories] # 创建示例电影绑定分类 movies_data [ {title: 流浪地球, rating: 8.4, category: categories[1], is_hot: True}, {title: 我不是药神, rating: 9.0, category: categories[2], is_hot: True}, {title: 千与千寻, rating: 9.3, category: categories[4], is_hot: True}, ] for item in movies_data: category Category.objects.get(nameitem[category]) Movie.objects.create( titleitem[title], ratingitem[rating], categorycategory, is_hotitem[is_hot], ) def unseed_movies(apps, schema_editor): # 回滚操作反向迁移时清空数据 Movie apps.get_model(movie, Movie) Movie.objects.all().delete() class Migration(migrations.Migration): operations [ migrations.RunPython(seed_movies, unseed_movies), ]这段脚本演示了一个专业技巧反转迁移时把数据删掉避免重复填充。写入后执行python manage.py migrate数据就自动进库了。答辩演示时我一般会准备三个必演场景一是在后台添加一部电影并立即可在前台看到展示系统完整的数据流转链路二是用页脚搜索框搜一个具体的电影名强调icontains模糊匹配的效果三是演示分类导航点击某个分类能看到只属于该分类的电影列表。这三个动线覆盖了 Model、View、Template 的全部工作流程评委能清楚地看到你不是只会拷贝代码而是理解了每个环节怎么串起来的。还有一个细节容易忽略换一台电脑或到答辩现场演示时数据库里的数据不会自动带过来。拷贝项目时记得连同db.sqlite3文件一起带走或者干脆在演示前用我上面写的 Data Migration 重建数据。我习惯采用后者因为db.sqlite3文件有时候会被.gitignore忽略拷来拷去容易漏掉。带上迁移脚本就不依赖任何外部文件新环境里执行两条命令就能完全重建数据python manage.py migrate python manage.py runserver这个习惯帮我避开过不止一次演示现场数据丢失的窘境希望你也能用得上。本文还有配套的精品资源点击获取