十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Python+Django小说网站源码实战:从模型设计到部署排坑

Python+Django小说网站源码实战:从模型设计到部署排坑 简介这是一套基于Python与Django框架开发的完整小说网站项目源码面向计算机专业本科生、毕业设计开发者及Web全栈初学者旨在提供可直接运行的小说阅读平台实践案例覆盖用户管理、小说分类、章节发布、阅读记录等核心功能模块。压缩包共851个文件包含61个Python后端逻辑文件、252个JavaScript前端交互脚本、115个Vue组件、69个CSS样式文件、84个PNG图标资源及30余个SCSS/LESS预编译样式另有APK安装包与调试用Android应用整体体积达460.8MB结构清晰、前后端分离特征明显。已有388人下载学习适合用于课程设计、毕设选题或Django工程化开发能力训练。读者可直接部署运行深入理解Django ORM建模、RESTful接口设计、静态资源管理及VueDjango混合渲染模式同时获得含数据库迁移脚本、管理员后台、响应式前端页面在内的全流程交付成果。 拿到这份“基于python和Django开发的小说网站项目源码.zip”的时候我的第一反应是这不会又是一个学生毕业设计的半成品吧这几年我找过不少自称“可运行”的Django项目里面缺依赖、漏迁移、模板硬编码的问题屡见不鲜。但把这个项目解压跑起来把几个核心页面点了一遍之后我的判断变了代码结构完整、功能闭环尤其是章节分页和用户书架这两块处理得比很多网上流传的源码都扎实。如果你刚开始学Django或者正在为毕业设计、个人作品集找一个能直接改的底子这份源码确实值得拆开来看看。这篇文章我不吹不黑我站在一个实际动手跑过、改过代码的人的角度把项目的设计思路、核心模块实现、源码使用步骤和排坑经验一次讲清楚。全文不涉及高大上的微服务架构也不讲什么花哨算法就是一套老老实实的大众级技术方案——但这类方案恰恰才是真正能跑上线的方案。适合看的读者有三类学Django学到入门但缺一个完整项目串联知识点的人需要快速搭出一个可演示系统的人还有想把网站改造成自己小说业务的个人开发者。你不需要懂很深的前端会点Python基础就能跟下来。1. 项目整体设计与技术选型1.1 为什么选PythonDjango而不是其他组合先说选型这件事。小说网站说白了就是一个典型的内容管理系统核心能力是内容录入、内容展示、用户管理和检索。这类系统的开发痛点是功能杂、迭代快、上线周期短选框架的第一标准不是性能极致而是“开发效率”和“功能覆盖度”。Django在这方面优势非常明显。它自带ORM、后台管理、用户认证和表单处理等于说一个内容站最费时间的基础模块框架已经给你铺好了一大半。对比FlaskFlask确实轻量灵活但是用户登录要自己写session、后台管理要自己搭第三方扩展、模型关联要自己设计对一个小团队或者独立开发者来说这些重复工作实在没必要。对比Node的Express开发效率和生态也不差但是如果团队的日常工作以Python为主爬虫脚本、数据处理管线都能和网站业务共用一套语言环境维护成本最低。再说一个国内开发者绕不开的问题Django在国内到底用得广不广说实话这几年很多新项目确实转向了Go和Node但Django在传统行业、企业内部系统、内容类网站里依然是高频选择。尤其是那些需要快速交付且有管理后台诉求的项目Django的admin机制能省出至少两周的编码量。小说站、资讯站、文档站这类重内容、轻交互的项目Django完全可以镇得住场子。1.2 小说网站的功能需求拆解一个能正常运转的小说网站表面上就那么几个页面但拆开来看业务逻辑并不少。我把这份源码的功能梳理成了四个部分用户侧注册、登录、个人书架、收藏记录。内容侧小说信息录入、封面图上传、作者管理、章节内容维护。展示侧首页推荐、分类列表、小说详情、阅读器翻页。管理侧基于Django admin二次定制的数据后台。这四个部分不是独立存在的。比如用户收藏一本书前台要能在阅读页和详情页都提供“加入书架”按钮小说状态从“连载中”改到“完结”列表页要能自动响应章节顺序调整了上一章、下一章要跟着变。这些交互看似细小但都是把项目从“能跑”变成“能用”的关键。1.3 整体架构设计源码采用的是标准的Django MTV架构没有引入复杂的前后端分离。请求流程是这样的浏览器发起请求后由urls.py负责路由分发把不同URL交给对应的视图函数处理视图层通过ORM操作数据库取数再把数据交给模板渲染成HTML返回给浏览器。整个链路清晰排查问题时能顺着流程快速定位。技术栈方面也比较“朴素”Python 3.8以上版本Django 3.x这套源码兼容2.2到4.x的常规写法SQLite作为默认开发数据库生产环境可以平滑切换MySQL前端使用Django模板加Bootstrap没有单独构建Vue或React的前端工程封面图采用本地文件存储开发期由MEDIA_URL直接访问。这套组合最大的好处是一个人也能从头到尾维护得动。你不需要额外启动一个node进程当前端服务器也不需要在服务器上维护两套代码项目目录结构简单清晰适合学习也适合小规模上线。2. 数据库设计与核心模型实现2.1 小说、章节、用户三类模型的字段设计用Django开发建模是最值得先做的事情。模型设计直接决定了后续业务的开发方式如果字段一开始没想清楚后面改起来会非常痛苦。这份源码里的核心模型主要围绕“小说”和“章节”展开再加上Django内置的User模型做用户扩展。from django.db import models from django.contrib.auth.models import User class Category(models.Model): name models.CharField(分类名, max_length50) class Meta: verbose_name 分类 verbose_name_plural 分类 def __str__(self): return self.name class Novel(models.Model): STATUS_CHOICES ( (serializing, 连载中), (finished, 已完结), ) title models.CharField(书名, max_length100) author models.CharField(作者, max_length50) category models.ForeignKey(Category, on_deletemodels.PROTECT, related_namenovels) intro models.TextField(简介) cover models.ImageField(封面图, upload_tocovers/, blankTrue, nullTrue) status models.CharField(连载状态, max_length20, choicesSTATUS_CHOICES, defaultserializing) created_time models.DateTimeField(创建时间, auto_now_addTrue) updated_time models.DateTimeField(更新时间, auto_nowTrue) class Meta: verbose_name 小说 verbose_name_plural 小说 def __str__(self): return self.title class Chapter(models.Model): novel models.ForeignKey(Novel, on_deletemodels.CASCADE, related_namechapters) title models.CharField(章节标题, max_length100) content models.TextField(正文) order models.PositiveIntegerField(章节序号, default0) class Meta: verbose_name 章节 verbose_name_plural 章节 ordering [order] def __str__(self): return f{self.novel.title} - {self.title}这里有几个字段设计细节值得细品。Chapter.content用TextField不用CharField是因为小说正文长度通常远超255字符CharField有长度限制TextField是专门为长文本设计的。order字段在很多项目里容易被忽略有些人直接用id排序但一旦遇到调整章节插入顺序的情况id排序就会出错有了独立的order字段才能保证目录顺序稳定。Novel.status用choices而不是直接存一个字符串主要是为后续扩展留余地比如以后增加“停更”状态。分类表的外键用了PROTECT而不是CASCADE这个选择也很讲究分类一旦被小说引用就不能直接删掉了防止误操作把一批小说连带清空。2.2 用户书架与收藏关系的绑定用户收藏是小说网站里用户黏性最高的功能。我没有直接用新建一张“书架表”存用户和书的对应关系而是利用了Django的ManyToManyField这样代码量少而且ORM直接提供了add、remove、filter等方法操作非常简单。class Novel(models.Model): # ... 其他字段省略 collected_users models.ManyToManyField( User, throughUserCollection, related_namecollected_novels, blankTrue, ) class UserCollection(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE, related_namecollections) novel models.ForeignKey(Novel, on_deletemodels.CASCADE, related_namecollections) created_time models.DateTimeField(收藏时间, auto_now_addTrue) class Meta: verbose_name 用户收藏 verbose_name_plural 用户收藏 unique_together (user, novel) # 视图中的典型用法 if request.user.is_authenticated: qs request.user.collected_novels.all()使用through定义中间模型好处是能额外保存“收藏时间”这类关联信息。如果你只想存一个简单对应关系可以不加through直接让Django自动建中间表但是真实项目中“我什么时候收藏的这本书”是有价值的所以我更推荐显式定义中间模型。unique_together(user, novel)从数据库层面保证同一个用户收藏同一本书不会出现重复记录。2.3 数据库索引与查询性能优化小说网站的数据量特征是有“长尾”小说数量可能是几千本但章节数量可能达到几十万甚至上百万。这时候查询性能就得提前做好考量。模型中我建议给Novel.title和Novel.author添加db_indexTrue因为前台搜索和列表页最频繁的就是这两个字段的模糊匹配。Chapter表则需要建立联合索引novel_id, order做阅读页翻页查询时指定小说按章节序号排序是使用频率最高的查询路径。Django中可以用Meta.indexes定义联合索引class Chapter(models.Model): # ... 字段省略 class Meta: ordering [order] indexes [ models.Index(fields[novel, order], namenovel_order_idx), ]有一个常见的性能坑是在渲染小说详情页时如果不小心用了chapter_set.all()再去循环统计章节数会触发额外查询。更好的做法是直接在Novel模型上用一个字段实时统计或者用annotate一次性查出章节数量from django.db.models import Count novel_list Novel.objects.annotate(chapter_countCount(chapters))这个技巧在首页推荐榜单非常实用不然N本书就会产生N1次查询页面一卡一卡的就是这么来的。3. 核心功能模块的实操实现3.1 用户注册登录与权限控制用户体系这部分源码用的是Django内置的认证框架。注册、登录、登出都是固定套路但有几个细节不翻车很难注意到。注册视图最容易被忽略的问题是密码处理。很多人图省事直接在数据库里存明文密码这是大忌。正确做法是使用User.objects.create_user()它会自动对密码做哈希处理。下面是常规的注册和登录实现from django.contrib.auth import authenticate, login, logout from django.contrib.auth.models import User from django.http import HttpResponse from django.shortcuts import render, redirect def register_view(request): if request.method POST: username request.POST.get(username, ).strip() password request.POST.get(password, ) password2 request.POST.get(password2, ) if not username or not password: return HttpResponse(用户名和密码不能为空) if password ! password2: return HttpResponse(两次密码不一致) if User.objects.filter(usernameusername).exists(): return HttpResponse(用户名已被注册) user User.objects.create_user(usernameusername, passwordpassword) login(request, user) return redirect(home) return render(request, register.html) def login_view(request): if request.method POST: username request.POST.get(username, ) password request.POST.get(password, ) user authenticate(request, usernameusername, passwordpassword) if user is not None: login(request, user) next_url request.GET.get(next, home) return redirect(next_url) return HttpResponse(用户名或密码错误) return render(request, login.html) def logout_view(request): logout(request) return redirect(home)代码里的next参数是个容易被忽略的关键点。用户在访问需要登录的页面时Django的login_required装饰器会跳转到登录页并在URL里加上?next/原来访问的地址/。登录成功之后如果没有正确处理next用户会被打回首页体验就很差。所以我建议登录视图一定要读取并跳转到request.GET.get(next)。除此之外在需要登录才能访问的视图函数上记得加login_required装饰器比如收藏管理、个人中心。不加的话匿名用户可以绕过前端隐藏按钮直接访问接口地址逻辑上就有漏洞了。3.2 小说录入与章节管理小说和章节的数据录入有两种途径一种是直接使用Django admin后台适合管理员录入另一种是在前台提供投稿表单适合普通用户或作者录入。这份源码两种都涉及admin为主前台投稿入口也预留了。先看基于ModelForm的前台小说录入表单from django import forms from .models import Novel class NovelForm(forms.ModelForm): class Meta: model Novel fields [title, author, category, intro, cover, status] def publish_novel_view(request): if not request.user.is_authenticated: return redirect(login) form NovelForm(request.POST or None, request.FILES or None) if request.method POST: if form.is_valid(): novel form.save(commitFalse) novel.creator request.user novel.save() return redirect(novel_detail, novel_idnovel.id) return render(request, publish_novel.html, {form: form})注意request.FILES必须传进表单构造方法否则cover封面图字段永远无法正常保存。还有commitFalse这一步它是为了在真正写库前把当前登录用户写入creator字段。如果表单里没有creator字段直接form.save()会报错因为它不知道这个字段的值从哪里来。admin端章节录入有个体验问题章节数量多的时候下拉选择框会变得又长又卡。Django 2.0以后官方推荐用autocomplete_fields优化这个体验它基于外键搜索接口实现一个异步搜索框章节多了也不会卡from django.contrib import admin from .models import Novel, Chapter admin.register(Chapter) class ChapterAdmin(admin.ModelAdmin): list_display [id, novel, title, order] list_filter [novel] search_fields [title] autocomplete_fields [novel] admin.register(Novel) class NovelAdmin(admin.ModelAdmin): list_display [id, title, author, category, status, updated_time] list_filter [status, category] search_fields [title, author] autocomplete_fields [category]注意要给NovelAdmin也加上autocomplete_fields [category]并且被引用的分类模型的admin上得实现search_fields。否则Django会提示你配置不正确。这个细节我当初第一次用的时候踩了坑。3.3 搜索与分类推荐功能搜索功能看起来简单但实现得好不好差别很大。新手最容易的做法是Novel.objects.filter(titlekeyword)这样只能精确匹配完整书名用户少打一个字就搜不到了。更合理的方案是用Q对象做多字段模糊查询from django.db.models import Q from django.core.paginator import Paginator def search_view(request): keyword request.GET.get(kw, ).strip() novels Novel.objects.all() if keyword: novels novels.filter( Q(title__icontainskeyword) | Q(author__icontainskeyword) | Q(intro__icontainskeyword) ).distinct() paginator Paginator(novels, 12) page request.GET.get(page, 1) page_novels paginator.get_page(page) return render(request, search.html, { novels: page_novels, kw: keyword, })icontains是大小写不敏感的模糊匹配MySQL里对应LIKE %keyword%。用Q对象把三个查询条件用“或”关联再把查询结果去重就覆盖了“书名记不全但记得作者”的场景。这个搜索方案虽然在大数据量下性能有瓶颈但对几千本小说的规模来说完全够用而且代码极好理解。分类推荐则是在首页展示每个分类下的热门小说最直接的方式是通过外键的反向关系查询最新更新def home_view(request): categories Category.objects.annotate(novel_countCount(novels)) for cat in categories: cat.hot_novels cat.novels.order_by(-updated_time)[:8] return render(request, home.html, {categories: categories})这里先annotate统计分类下小说数量再循环为每个分类取前8本最近更新的小说。循环N1次查询在这个场景是可接受的因为分类数量一般不超过20个网页响应时间不会受影响。3.4 阅读页面与上一章下一章阅读页是小说网站的核心体验入口。逻辑很明确根据小说ID和章节ID取正文同时提供上一章、下一章导航。这个功能看起来简单但我在很多源码里看到过错误写法——用id大小来判断相邻章节。正确的做法是基于order字段查询相邻章节def chapter_detail_view(request, novel_id, chapter_id): novel get_object_or_404(Novel, pknovel_id) chapter get_object_or_404(Chapter, pkchapter_id, novelnovel) prev_chapter Chapter.objects.filter( novelnovel, order__ltchapter.order ).order_by(-order).first() next_chapter Chapter.objects.filter( novelnovel, order__gtchapter.order ).order_by(order).first() return render(request, chapter_detail.html, { novel: novel, chapter: chapter, prev_chapter: prev_chapter, next_chapter: next_chapter, })用order__lt和order__gt配合排序取首条记录无论是顺序阅读还是跳转逻辑都是自洽的。注意两个地方都必须过滤novelnovel不然不同小说的章节会串场。另外章节目录页建议做分页显示如果一本书有6000章一次性渲染全部章节链接浏览器都会明显卡顿。用Django的Paginator组件处理成每页100条是最省事的方案。4. 常见问题与排查技巧实录4.1 中文显示乱码与数据库字符集小说网站的项目全都是中文内容乱码问题一出现基本就没法用了。开发时使用SQLite数据库通常不会遇到字符集问题但切到MySQL之后这个问题非常典型。如果创建数据库时没有显式指定字符集默认可能是latin1导致中文数据存进去之后显示成问号。解决方案是在创建数据库时指定utf8mb4CREATE DATABASE novel_site DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;同时在Django的settings.py里对应配置DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: novel_site, USER: 你的用户名, PASSWORD: 你的密码, HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, }, } }如果表已经建好了才改数据库字符集可以用ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4但这只是补救措施最省心的还是建库的时候一步到位。4.2 封面图上传失败与静态文件404图片上传和静态文件是排查时间的大户。开发模式下Django本身不处理图片服务需要在项目的urls.py里追加媒体文件路由from django.conf import settings from django.conf.urls.static import static urlpatterns [ # ... 其他路由 ] if settings.DEBUG: urlpatterns static(settings.MEDIA_URL, document_rootsettings.MEDIA_ROOT)settings.py里要确保MEDIA_URL /media/ MEDIA_ROOT BASE_DIR / media如果上传了封面但是在页面上图片不显示先检查媒体文件是否真的落到了MEDIA_ROOT目录下。如果covers/目录没有生成或者权限不对上传就会失败。Windows下目录权限基本没问题Linux服务器要手动加可写权限chmod -R 755 media/还有一个非常隐蔽的坑Pillow库没安装。ImageField依赖Pillow处理图片如果你本地环境没有安装表单校验会直接报错。解决办法就是pip install pillow这个在requirements.txt里必须带上。4.3 列表分页与大数据量下的性能优化小说网站的性能瓶颈主要集中在“章节目录”和“书架列表”两个地方。章节目录动辄上百条记录书架列表加上封面图查询也会越来越重。很多初学者会用Novel.objects.all()[offset:offsetlimit]自己手写分页虽然能跑但总会遇到边界问题。Django自带的Paginator已经处理好了页数、页码验证、last_page等细节直接用就行from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger def novel_list_view(request): novel_list Novel.objects.select_related(category).order_by(-updated_time) paginator Paginator(novel_list, 12) page request.GET.get(page, 1) try: novels paginator.page(page) except PageNotAnInteger: novels paginator.page(1) except EmptyPage: novels paginator.page(paginator.num_pages) return render(request, novel_list.html, {novels: novels})这里用了select_related(category)避免在模板里访问novel.category.name时对每本书都额外发一条SQL查询。对于外键关联这种正向查询select_related是性价比极高的优化手段。当某个小说的章节数达到几万章时翻页到最后一页会明显变慢因为数据库的LIMIT offset要扫描前面所有记录。一个实用的优化是用“键集分页”代替“偏移量分页”——先按上一页最后一条记录的order值过滤再取下一页。这个优化对按顺序阅读的场景尤其有效# 伪代码示意 last_order request.GET.get(last_order, 0) next_chapters Chapter.objects.filter( novelnovel, order__gtlast_order ).order_by(order)[:20]这种方式的翻页速度与页码深浅无关是数据量变大以后值得踩的优化方向。4.4 部署阶段的高频报错本地跑通之后部署到服务器至少有四个高频问题你一定会遇到。第一个是ALLOWED_HOSTS配置。DEBUGFalse的时候Django要求你显式列出允许访问的域名不然直接抛DisallowedHost异常。改成ALLOWED_HOSTS [你的域名, 服务器的IP地址]第二个是静态文件不生效。生产环境下runserver不再代理静态文件需要执行python manage.py collectstatic把所有静态文件集中到STATIC_ROOT目录再用nginx或CDN指过去。第三个是DEBUGFalse后模板错误信息不再显示页面变成500。此时要去查看日志别在浏览器里瞎猜。第四个是Django版本和Python版本不匹配导致的启动失败。比如Django 2.2在Python 3.5以下可能装不上Django 4.x要求Python 3.8以上。下载源码后先看requirements.txt里锁的版本再创建虚拟环境能避开一半的坑。5. 源码使用与本地运行步骤5.1 环境准备与虚拟环境搭建不管源码压缩包是从哪个渠道下载的拿到之后第一件事永远是解压、看README、看requirements.txt。这份源码我建议你在本地用虚拟环境运行避免把系统Python环境搞乱。# 如果是Windows python -m venv venv venv\Scripts\activate # 如果是macOS或Linux python3 -m venv venv source venv/bin/activate激活虚拟环境后安装依赖pip install -r requirements.txt如果requirements.txt里没有锁定具体版本我建议手动安装一个稳定的组合pip install django3.2.25 pillowDjango 3.2是LTS长期支持版本兼容性很好网络上能找到的资料最多出问题最容易搜索到答案。别一上来就装Django 5.x虽然新版本功能多但有些老项目的写法不一定完全兼容没必要在版本适配问题上浪费精力。5.2 settings.py配置修改启动项目之前至少要改几个配置项。打开源码目录下的settings.pySECRET_KEY 替换成你自己的随机字符串 DEBUG True ALLOWED_HOSTS [*] LANGUAGE_CODE zh-hans TIME_ZONE Asia/ShanghaiSECRET_KEY是Django的签名密钥源码包里可能会带一个现成的上线之前必须换成自己的不然会有安全隐患。LANGUAGE_CODE改成zh-hans后admin后台会显示中文界面这对中文小说管理系统来说体验好很多。如果要用MySQL替代默认的SQLite需要在DATABASES里配置连接信息。开发调试阶段我建议先用SQLite零配置、随开随用把业务跑通了再切换MySQL减少一开始的变量。5.3 数据迁移与初始化数据数据库建表是固定节奏python manage.py makemigrations python manage.py migrate python manage.py createsuperuser python manage.py runserver执行完runserver之后浏览器访问http://127.0.0.1:8000就能看到网站首页。接着访问http://127.0.0.1:8000/admin用刚才创建的超级管理员账号登录后台先添加几个小说分类再添加小说、上传封面、录入章节。这些数据录入保存后刷新前台页面就能看到效果。如果你希望快速看到演示数据有些源码包里会附带fixtures目录里面存放了JSON格式的初始数据。可以通过python manage.py loaddata fixtures/initial_data.json一键导入。没有fixtures也没关系手动录几本书、几十个章节也就十分钟的事顺便还能把admin后台的操作流程熟悉一遍。5.4 项目目录结构快速摸底源码拿到手不要急着跑先花两分钟看目录结构理解每个文件的位置后面改代码会顺畅很多。典型的Django项目结构是这样的novel_site/ ├── manage.py ├── requirements.txt ├── novel_site/ # 项目配置目录 │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── app/ # 小说业务应用 │ ├── migrations/ # 数据库迁移文件 │ ├── __init__.py │ ├── admin.py # 后台管理配置 │ ├── models.py # 数据模型 │ ├── views.py # 视图函数 │ ├── urls.py # 子路由 │ ├── forms.py # 表单定义 │ └── apps.py ├── templates/ # 模板目录 │ ├── base.html │ ├── home.html │ ├── novel_detail.html │ └── ... ├── static/ # 静态文件目录 │ └── ... └── media/ # 上传文件目录 └── covers/理解了一个Django项目的物理结构你以后再拿别的源码上手时间至少省一半。6. 二次开发的一些思路源码跑通只是第一步真正有价值的是你基于它做二次开发。我根据自己维护项目的经验给你几个可以动手的方向。第一个方向是给分类加上“人气热度”字段。目前首页推荐的排序规则是updated_time倒序也就是说哪个小说最近更新了章节哪个就排前面。但一个真实的小说站热度排行才是用户更关注的。可以给Novel加一个click_count整数字段详情页每次被访问就加一再用这个字段做排序。注意这个简单的计数器在高并发下会有一定损耗不过个人站点的量级完全不用在意。第二个方向是做全文搜索替代LIKE查询。目前搜索功能用的是数据库LIKE模糊匹配在几千本小说规模下没问题但如果章节内容也纳入搜索这个方案就会变慢而且不准。可以引入Django Haystack配合Whoosh做全文索引或者直接把搜索引擎服务接进来。对个人项目来说这是很不错的加分题。第三个方向是手机端适配。模板默认用的是Bootstrap响应式基础已经有了但是阅读页的字体大小、行间距在手机上还有很大优化空间。这块是纯前端工作改起来不涉及后端逻辑是一个适合练手的方向。第四个方向是把封面图存储迁移到对象存储。本地存储在小规模够用但图片多了以后占磁盘、备份麻烦迁移到云上配置也不复杂只需要改一下存储后端就可以了。源码里所有封面图相关的HTML和模型字段都不需要改动因为Django的FileField抽象层把底层存储差异屏蔽掉了。我觉得做二次开发最重要的原则是先想清楚你要的核心卖点是什么再动手。不要什么功能都想加不要一上来就重构数据库。基于这套源码稳定迭代几个版本效果会比推翻重写好很多。写作期间我又试着往里面加了一个“阅读记录”功能做法是在UserCollection基础上加一个last_read_chapter外键这样用户点进书架就能看到上次读到哪一章。核心改动不到三十行代码但整个体验提升了一个档次。这类小而精准的功能才是从“抄源码”走向“做产品”的正确方向。本文还有配套的精品资源点击获取
返回列表