2026/10/16 7:08:12

基于Python的作家信息管理系统:数据库设计与Web开发全讲解

基于Python的作家信息管理系统:数据库设计与Web开发全讲解 先把结论放在前面这个题目能做好核心不在于“作家管理”这四个字而在于你把它做成一个数据关系清晰、功能完整、有亮点可讲的信息管理系统。很多同学毕设选题时会下意识挑一个“看起来不会太难”的题目但交题时才发现功能太简单撑不起论文结构代码太单薄扛不住答辩追问。作家信息管理系统恰好卡在“复杂度适中”的位置——它可以拆出增删改查、数据关联、检索筛选、图表统计、导入导出等模块让每一章PPT都有内容可讲同时用Python实现起来并不劝退。我前后带过不少毕设项目也帮人排查过同类系统里的各种“坑”。这篇文章就把这个题目从选题、表设计、框架选型、编码实现到答辩前最容易被追问的细节一次性拆开讲清楚尽量做到你照着思路能自己搭出一套能跑、能讲、能过审的系统。1. 项目整体拆解作家信息管理系统到底要做成什么样1.1 先想清楚“管理”的边界在哪里很多人拿到这个题目第一反应是“建一个表存几个作家的名字、简介、代表作品”然后就开始写代码。这种思路做出来的东西不叫管理系统叫“留言板”。管理系统和管理工具的本质区别在于前者有“业务闭环”。也就是说系统里存放的信息是可以被创造、更新、检索、统计、移除的并且信息之间有关联关系而不是孤零零地躺在表格里。作家信息管理系统如果只存一个作家表那数据只有一维如果你把“作家”和“作品”拆成两个表再通过外键关联起来就多了一个维度如果再加上“出版社”“书籍分类”“出版年份”你就有了一张能支撑查询、筛选、统计的信息网。所以我在划分功能前建议先画一张业务草图谁在用这个系统管理员要做什么普通访客能看什么作家本人的信息由谁维护把所有角色和操作列出来功能自然就浮出来了。1.2 基础功能模块划分与优先级一个合格的作家信息管理系统至少要包含以下模块作家信息管理作家姓名、笔名、国籍、出生年月、文学流派、个人简介、头像照片、联系方式。作品信息管理作品名称、作品类型、字数、状态连载中/已完结、发布时间、所属作家、封面图片。出版社信息管理出版社名称、所在地、成立时间、代表作列表。作品可以关联到出版社形成完整的出版链条。分类管理用于区分作品类型小说、散文、诗歌、评论、剧本等一般用简单的树形或单层分类即可。用户与权限管理员账号可以操作全部数据普通用户只能浏览查询不需要太复杂。数据统计按作家作品数量排行、按分类统计作品分布、按年份统计出版趋势。一周目开发时把1-5做扎实第6项用图表展示毕设的结构就已经非常完整。再往深做还可以加作品评论、收藏、Excel批量导入、PDF导出、操作日志等功能这些属于“加分项”可以放在基本功能稳定之后再做。1.3 角色与权限为什么必须要有登录机制我之前审过不少学生做的系统最典型的问题是“所有功能摆在大厅里谁都能改数据”。答辩时老师一上来就问你这个系统没有登录怎么区分管理员和普通用户数据被误删了怎么办这两个问题只要问出来后面答得再好也会很被动。我的建议是最少做两级角色管理员admin和普通用户user。管理员可以进入后台进行数据的增删改普通用户只能查看首页、详情页和查询结果。有些系统还可以加“作家自助登录”的角色让作家本人维护自己的信息和作品但这会让权限逻辑变复杂不适合作毕设的第一版。先把两级角色做干净后续想在论文里加内容再去扩展。登录模块看起来像“标配”但它是你数据库设计、后端逻辑、前端页面三层之间最早建立联系的地方也是答辩中容易被追问的高频区域——用户密码怎么保存用了什么加密方式Session 和 Token 有什么区别这些问题都是可以提前准备的“送分题”。2. 技术选型为什么是Python以及Django、Flask怎么选2.1 Python做毕设的天然优势选Python做管理类系统说白了就三个理由上手快、生态全、资料多。管理信息系统逻辑上不涉及高并发、高复杂度计算Python完全吃得消而它对字符串处理、Excel操作、简易爬虫、数据可视化的支持又比Java、PHP省太多事。对于毕设的学生来说时间是最紧张的资源Python可以把“从零到能跑”的周期压得非常短。此外Python的ORM对象关系映射对“不会写复杂SQL”的同学极其友好。比如我们要查“所有作品数量大于3的作家”Django里用一行Annotate就能搞定换成原生SQL你还要纠结GROUP BY和HAVING。这对论文里写“系统采用ORM技术对数据库进行操作”也更有说头。2.2 Django还是Flask没有绝对答案但有更适合的场景这是每个做Python毕设的人都要过的“选择题”。我的看法是如果系统需要后台管理、带登录鉴权、而且你希望少写重复代码那就选Django。Django自带Admin后台、认证系统、ORM、表单处理、静态文件管理这些对于“作家信息管理系统”这种重CRUD、轻定制的项目几乎是量身定做。你用Django自带的Admin甚至可以在没写一行前端代码的情况下先把数据管理起来这对中期检查时“打个Demo”非常有价值。Flask的优势是轻量、灵活适合你想把每个环节都掌控在自己手里的情况。但代价是——用户认证要自己写数据库迁移要自己配表单校验要自己造轮子。对于基础不太扎实、时间又紧的同学我不建议在Flask上硬啃这些没必要。有人问我“哪个写在简历上更好看”说句实在话Django和Flask都只是工具面试官问的是“你用它做了什么、你怎么思考的”而不是“你背过多少框架API”。你选一个用熟、用透能讲清楚它的架构特点比泛泛地用过两个框架强得多。补充如果有一个学弟学妹跑来问我Ta的需求是“要后台界面漂亮、开发速度快、代码结构清晰”我会直接推荐Django 前端模板语言再配一个现成的后台模板。这一套是最稳的。2.3 前端方案服务端模板还是前后端分离现在的毕设前端很容易被带跑偏。有人在知乎上看到“前后端分离是主流”就非要用Vue Django REST Framework自己写登录页面然后被跨域问题折磨两天。我的观点很直接如果时间允许、你的前端基础还行前后端分离确实能做出更“现代”的交互感但如果你是零基础速成选Django自带的模板渲染DTLBootstrap已经完全够用。“作家信息管理系统”的数据操作大多是对表单的提交和表格的展示用模板渲染完全不存在性能瓶颈。而且模板表单提交的好处是逻辑清晰前端POST一个表单后端视图接收处理再重定向回列表页。你不用处理前端校验、API异常、Token过期这些额外复杂度。毕业设计答辩看的不是“你用了几个框架”而是“你是否理解了系统是如何运作的”。模板渲染这套模式反而好讲、好理解。2.4 数据库的选型和ORM的价值数据库建议首选SQLite第二选择是MySQL。如果项目只是本机运行、数据量在几千条级别SQLite完全够用并且它零配置、文件即数据库拷贝就能迁移。如果你未来想部署到服务器或者要演示“连接远程数据库”这种技术点那就换MySQL。ORMDjango自带用起来像“操作Python对象一样操作数据库表”虽然它生成的SQL有时候不是最优但作为毕设系统便于阅读和维护比死磕性能更重要。有一说一ORM带来的安全感是巨大的——你不太容易写出SQL注入漏洞因为ORM参数是经过转义的。这个点你在论文里写“系统基于ORM进行数据库操作有效防止SQL注入攻击”老师会认为你有安全意识。3. 数据库设计作家信息管理系统的核心数据模型3.1 从业务出发拆解数据表数据库设计是所有管理系统项目的“地基工程”。一张表走天下的后果是后期加功能时冗余字段爆炸查询逻辑混乱答辩时一被问“你的表关系”就卡壳。我把“作家信息管理系统”拆成五张核心表Writer作家表存放作家基本信息。Work作品表存放作品信息通过外键关联到作家表。Publisher出版社表存放出版社信息。Category分类表存放作品类型。User用户表用Django默认的User表即可也可以扩展Profile字段存昵称、头像等。除此之外如果做了“作品收藏”“评论”功能再额外加关联表。下面先看核心表结构。3.2 各核心数据表的字段设计Writer表建议字段字段类型说明nameCharField作家姓名必填pen_nameCharField笔名可空nationalityCharField国籍birth_dateDateField出生日期genreCharField代表流派introTextField个人简介avatarImageField头像照片created_atDateTimeField创建时间自动注意几点pen_name一定允许为空因为很多作家的本名不公开avatar使用ImageField时要配合Pillow库Django项目需要提前在配置里设置好MEDIA_ROOT和MEDIA_URL否则上传图片会报错birth_date不要用字符串用日期类型否则后续按年代筛选时没法比较大小。Work表建议字段字段类型说明titleCharField作品名writerForeignKey关联作家表categoryForeignKey关联分类表publisherForeignKey关联出版社表word_countIntegerField字数statusCharField连载中/已完结publish_dateDateField出版时间coverImageField封面图summaryTextField内容简介这里的关联字段在Django中写成这样writer models.ForeignKey(Writer, on_deletemodels.CASCADE, related_nameworks)on_deletemodels.CASCADE的含义是当作家被删除时其名下所有作品也会一并删除。这在数据管理上是合理的但要注意在真实场景中应该加一个“二次确认”弹窗防止误删。分类表、出版社表比较简单字段有名称和描述即可。User表的扩展from django.contrib.auth.models import User class Profile(models.Model): user models.OneToOneField(User, on_deletemodels.CASCADE) nickname models.CharField(max_length50, blankTrue) avatar models.ImageField(upload_toavatars/, blankTrue)用OneToOneField扩展内置用户模型是Django推荐的做法不会破坏原本认证逻辑又能加上自己的定制字段。3.3 外键和级联哪些设计要在意外键关系是整个系统里最容易讲出深度的地方。我用一个生活化类比来解释作家和作品就像“妈妈和孩子”妈妈不在了孩子的抚养信息当然也就不需要了这就是级联删除。出版社和作品的关系更像“临时合作”出版社倒闭了书不应该从世界上消失只是出版信息没有了而已。所以出版社和作品之间的外键建议设置SET_NULL前提是出版社字段允许为nullpublisher models.ForeignKey(Publisher, on_deletemodels.SET_NULL, nullTrue, related_nameworks)这样一来系统里就会有两种外键处理方式级联删除与置空删除。放在论文里可以写“系统根据业务语义的不同对关联数据分别采用级联删除与置空删除策略兼顾数据完整性与操作安全性”这句话含金量比写十行代码都高。外键设计时还要注意related_name的命名它会直接影响Django查询的写法。比如上面写了related_nameworks你就可以用writer.works.all()拿到一个作家所有作品如果不写Django默认通过work_set查询语义不够直观。4. 核心功能实操从零搭建系统骨架与关键模块4.1 环境准备与项目初始化项目名字我建议取一个贴合的英文名比如writer_manage不要用中文也不要太随意。初始化流程如下# 创建虚拟环境 python -m venv venv # 激活Windows venv\Scripts\activate # 激活macOS/Linux source venv/bin/activate # 安装 Django pip install django # 创建项目 django-admin startproject writer_manage # 创建一个应用 cd writer_manage python manage.py startapp writers创建完应用后记得在settings.py中把writers加到INSTALLED_APPS里INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, writers, # 新增 ]然后先跑一下迁移把Django内置的表用户、会话等建好python manage.py makemigrations python manage.py migrate python manage.py createsuperuser记住这个顺序。很多新手一上来直接写模型然后卡在makemigrations报错就是因为环境层面的迁移还没拉通。4.2 作家信息增删改查Django的实现思路与代码演示CRUD是管理系统的主干。对Django来说最简单快捷的方式是用函数视图 模板渲染。下面我以作家添加功能为例写一个完整闭环。先定义表单用Django的ModelForm# writers/forms.py from django import forms from .models import Writer class WriterForm(forms.ModelForm): class Meta: model Writer fields [name, pen_name, nationality, birth_date, genre, intro, avatar] widgets { intro: forms.Textarea(attrs{rows: 4, class: form-control}), birth_date: forms.DateInput(attrs{type: date, class: form-control}), }然后写视图# writers/views.py from django.shortcuts import render, redirect, get_object_or_404 from .models import Writer from .forms import WriterForm def writer_create(request): if request.method POST: form WriterForm(request.POST, request.FILES) if form.is_valid(): form.save() return redirect(writer_list) else: form WriterForm() return render(request, writers/writer_form.html, {form: form}) def writer_list(request): writers Writer.objects.all().order_by(-created_at) return render(request, writers/writer_list.html, {writers: writers}) def writer_update(request, pk): writer get_object_or_404(Writer, pkpk) if request.method POST: form WriterForm(request.POST, request.FILES, instancewriter) if form.is_valid(): form.save() return redirect(writer_list) else: form WriterForm(instancewriter) return render(request, writers/writer_form.html, {form: form}) def writer_delete(request, pk): writer get_object_or_404(Writer, pkpk) if request.method POST: writer.delete() return redirect(writer_list) return render(request, writers/writer_confirm_delete.html, {writer: writer})这与Django官方文档的示例风格一致但我在实际项目里调整了三点form.save()直接保存不需要手动.commit()因为表单里没有额外要处理的字段视图末尾的redirect必须写成功后的跳转地址避免重复提交删除操作用的是POST请求通过一个隐藏表单按钮提交而不是GET因为GET请求执行删除操作是安全隐患。答辩时能说出这一点会加印象分。再配合URL配置# writers/urls.py from django.urls import path from . import views app_name writers urlpatterns [ path(, views.writer_list, namewriter_list), path(create/, views.writer_create, namewriter_create), path(int:pk/update/, views.writer_update, namewriter_update), path(int:pk/delete/, views.writer_delete, namewriter_delete), ]这样作家模块的增删改查就通了。作品、出版社模块同理模板结构也类似复制一套微调即可。4.3 作品管理中的“外键下拉选择”与级联展示作品表单里作家、分类、出版社都是以“下拉框”的形式选择。这是DjangoModelChoiceField自动完成的但有一个体验细节要注意作品列表页面需要展示“属于哪个作家”而Django模板中取外键字段的方式是{{ work.writer.name }}。如果希望“点进作家详情页能看到名下所有作品”则在作家详情视图里用def writer_detail(request, pk): writer get_object_or_404(Writer, pkpk) works writer.works.all() # 顺便统计作品数量 work_count works.count() return render(request, writers/writer_detail.html, { writer: writer, works: works, work_count: work_count, })这里writer.works能直接用靠的就是前面related_nameworks的外键定义。这比写Work.objects.filter(writerwriter)更简洁也更能体现你理解了外键关系的反向查询。模板中展示{% for work in works %} div classcard h3{{ work.title }}/h3 span{{ work.category.name }}/span span{{ work.publisher.name }}/span span{{ work.publish_date }}/span /div {% empty %} p该作家暂无作品。/p {% endfor %}注意{% empty %}的用法它可以处理“作家没作品”的情况避免前端报错。4.4 搜索、筛选与分页让系统具备“查询”能力管理系统只做增删改查会显得功能简陋加上搜索和筛选才算有“信息管理”的味道。搜索逻辑很简单用icontains做模糊匹配。from django.db.models import Q def writer_search(request): query request.GET.get(q, ) writers Writer.objects.filter( Q(name__icontainsquery) | Q(pen_name__icontainsquery) | Q(intro__icontainsquery) ) return render(request, writers/writer_list.html, {writers: writers, query: query})筛选推荐用URL参数的方式传递比如按国籍筛选?nationality中国。这种“查询参数后端过滤”的方式回溯性好也方便拼接分页链接。分页用Django自带的Paginatorfrom django.core.paginator import Paginator def writer_list(request): all_writers Writer.objects.all().order_by(-created_at) paginator Paginator(all_writers, 10) # 每页10条 page_number request.GET.get(page) page_obj paginator.get_page(page_number) return render(request, writers/writer_list.html, {page_obj: page_obj})模板中渲染分页控件时要注意保留查询参数q、nationality用Django的查询参数拼接方式否则翻页之后搜索条件就丢了。这个小细节写进论文的“系统难点与解决”部分非常加分。4.5 数据可视化给系统加一个统计面板系统如果只有表格视觉上不够亮眼。建议加一个“数据概览”页用图表展示以下三类数据各作家作品数量排行柱状图作品类型分布饼图出版年份趋势折线图推荐使用轻量级前端图表库以ECharts的方式嵌入模板。你不需要自己从零配置复杂前端构建工具直接通过CDN引入echarts.min.js把后端统计好的数据用JSON格式渲染到模板里即可。后端取数from django.db.models.functions import TruncYear def stats(request): # 作家作品数量排行 writer_stats Writer.objects.annotate(work_nummodels.Count(works)).order_by(-work_num)[:10] # 按年份统计作品出版数量 year_stats Work.objects.annotate(yearTruncYear(publish_date)).values(year).annotate(countmodels.Count(id)).order_by(year) data { writer_names: [w.name for w in writer_stats], writer_work_nums: [w.work_num for w in writer_stats], year_labels: [str(y[year])[:4] for y in year_stats], year_counts: [y[count] for y in year_stats], } return render(request, writers/stats.html, {data: data})模板里用json_script将数据传到前端注意不要直接用{{ data|safe }}这样插值容易不转义且体积大。{{ data|json_script:chart-data }} script const data JSON.parse(document.getElementById(chart-data).textContent); // 然后初始化ECharts图表 /script用json_script的方式安全、简洁Django会自动转义。到了答辩时你还能说“我考虑了XSS安全问题使用Django内置的json_script过滤器传递数据。”这又是一个亮点。4.6 Excel批量导入与导出从进阶功能到“意外收获”想给系统再加点含金量可以做Excel导入导出。用openpyxl库实现十几行代码就能搞定。导出作家的Excelimport openpyxl from django.http import HttpResponse def export_writers_excel(request): wb openpyxl.Workbook() ws wb.active ws.append([姓名, 笔名, 国籍, 出生日期, 代表流派, 简介]) for writer in Writer.objects.all(): ws.append([writer.name, writer.pen_name, writer.nationality, writer.birth_date, writer.genre, writer.intro]) response HttpResponse(content_typeapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet) response[Content-Disposition] attachment; filenamewriters.xlsx wb.save(response) return response导入的时候要注意Excel里的“出生日期”可能是字符串也可能是日期对象要先统一转换格式再落库否则Django报格式错误。批量导入前还建议先做个“模板下载”让用户按模板填数据能省下很多格式兼容的问题。这一套折腾完你的系统已经从“能跑的CRUD”变成了“有导入导出、有数据可视化、有搜索分页”的完整项目写在简历上也不心虚。5. 常见问题与排查实录我在实际编码中踩过的坑5.1 中文乱码问题源头与解决路径很多人第一次跑Django项目时会遇到控制台输出乱码、Admin后台显示乱码、Excel导出乱码等等。排查这类问题不要只盯着一个地方要检查三处数据库编码是否支持中文。SQLite默认支持UTF-8MySQL需要看一下建库时字符集是否为utf8mb4。Django连接配置里加没加OPTIONS。连接MySQL时建议在配置中指定DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: writer_db, USER: root, PASSWORD: yourpassword, HOST: 127.0.0.1, PORT: 3306, OPTIONS: {charset: utf8mb4}, } }Excel导出的字符集问题。除非是导出CSV否则用openpyxl生成的是真正的xlsx文件不存在中文乱码问题。如果你非要生成CSV在写入HttpResponse时需要加\ufeffBOM头否则Windows Excel打开会乱码。中文乱码最折磨人的是“看起来一模一样的环境别人没事你有事”。我的经验是从最简单的输出开始排查——先在视图里打印一下数据确认后端是否有乱码再查模板渲染后的HTML源码最后再查数据库存储。层层定位不要瞎猜。5.2 静态文件404CSS、图片加载不出来的排查Django在开发阶段静态文件由django.contrib.staticfiles处理依赖STATIC_URL和STATICFILES_DIRS的配置。我在项目中的做法STATIC_URL /static/ STATICFILES_DIRS [BASE_DIR / static]如果你的页面用了Bootstrap本地文件需要把bootstrap.min.css等文件拷贝到static/目录下模板里用{% load static %} link relstylesheet href{% static css/bootstrap.min.css %}媒体文件图片上传则要用MEDIA_URL /media/ MEDIA_ROOT BASE_DIR / media并在项目的urls.py中追加from django.conf import settings from django.conf.urls.static import static urlpatterns static(settings.MEDIA_URL, document_rootsettings.MEDIA_ROOT)最常见的404原因是STATICFILES_DIRS配了但目录不存在或者页面里直接写img src/media/xxx.jpg而忘了在项目中挂载media路由。排查时先看浏览器Network请求对应的状态码如果是404再逐一确认路径映射。5.3 数据库表无法迁移外键与迁移顺序陷阱Django迁移时常见的报错是“ValueError: The field writers.Work.writer was declared with a lazy reference to writers.writer, but ...”这通常是因为模型相互引用时类名写错或者跨应用引用了不存在的应用标签。解决办法是把外键字段的引用写全比如from .models import Writer在应用顶部导入在FK中使用Writer而不是writers.Writer不出问题没必要加引号。还有一个很隐晦的坑你自己手动改了数据库表名或删过迁移文件导致本地数据库状态和迁移文件对不上。我的建议是开发早期不要手工改动数据库表结构严格通过makemigrationsmigrate完成 如果实在乱了重新建库比徒手修快得多。5.4 图片上传后界面不显示媒体路由与请求路径图片上传成功后列表页却不显示很多人会一头雾水。这种情况几乎都是因为模板里写的图片地址不对。正确渲染方式img src{{ writer.avatar.url }} alt{{ writer.name }}writer.avatar.url是Django处理后的完整媒体URL它会根据MEDIA_URL自动拼出路径。不要自己拼接/media/{{ writer.avatar }}——虽然表面上路径一样但一旦未来的配置变了手动拼接的代码就废了。模板里遇到ImageField、FileField第一反应就是用它自带的.url属性。5.5 常见问题速查表开发中遇到“怪现象”时先查这张表症状可能原因解决建议表单提交后数据没保存视图里没有判断request.method POST补上条件判断图片上传时报错没装 Pillow执行pip install pillow外键显示的是一串对象名模型没定义__str__给模型写__str__返回名称字段模板里读不到writer.works外键没写related_name补上相关名称后重新迁移点击删除按钮没反应删除表单的actionURL 没匹配检查URL名称与视图页面总是找不到模板模板目录没配置或命名不对建议App下建templates/writers/目录保持唯一分页之后搜索条件丢失模板分页链接没带query参数在分页链接里拼接?q...部署服务器后静态文件全挂没跑collectstatic执行python manage.py collectstatic这张表是我从十几个项目里总结出来的高频问题。如果开发中遇到其他疑难也有一个万能的排查思路先在视图里打印数据再查看HTML源码最后看浏览器Console和Network几乎所有问题都能在这三步里定位到。6. 别小看部署与演示环节这一步最能体现工程素养系统写完了最重要的一步反而不是继续加功能而是“演示环节能不能顺利跑起来”。我见过太多项目在本地能跑一到答辩现场就开始“表演事故”数据库没迁移、依赖包缺失、端口被占用、后台数据被清空……这些事极其影响答辩印象。我建议你在答辩前做三件事第一把你的依赖导出到一个文件里pip freeze requirements.txt这样到时候换到别的电脑上一条pip install -r requirements.txt就能恢复环境。第二把你的系统做成一个可以一键启动的脚本或者至少写清楚启动步骤python manage.py makemigrations python manage.py migrate python manage.py createsuperuser python manage.py runserver把这几行写在项目的README里。答辩时老师问“你项目怎么跑”你直接打开README念专业感拉满。第三提前准备一份演示数据。不需要多要真实。比如录入6-8位不同国籍、不同流派的作家每位配2-3部作品再设置若干出版社。演示搜索和统计的时候这张数据集能直接展现系统功能不用临时录入。收尾做系统容易讲清楚系统才是关键做这个题目最大的价值不在代码量而在于你通过它建立起了对“信息管理系统”的完整理解。你看一个看似普通的作家信息管理系统拆出来有用户权限、数据建模、CRUD、搜索分页、数据可视化、文件导入导出任何一个单独模块都能写出一小节论文任何一个模块都能应对一次追问。我个人对这些模块的编码顺序的建议是先搭项目骨架再做认证登录再做作家模块然后做作品和出版社搜索分页和统计靠后导入导出有精力就做。这个顺序的好处是每一步的产出都是可运行的每一步都不是白干。最后再分享一个小技巧写论文的时候不要光写“系统实现了什么”把每一步“为什么这么选择”写出来比如为什么Django的ORM能防SQL注入、为什么删除作品时用级联删除、为什么分页能降低数据库压力。面试官和论文老师最想看到的不是你会调包而是你理解了代码背后的原理。这个项目后续如果想继续扩展方向也很明确加评论系统、加作品在线阅读章节管理、加爬虫自动采集作家信息、做前后端分离改造甚至可以加推荐算法给读者推荐同风格作家。把这些写进论文的“未来展望”部分就是一个很自然的收尾。