Django新手练手项目:带登录功能的诗歌展示网站源码 本文还有配套的精品资源点击获取简介一个专为Django初学者准备的轻量级Web项目开箱即用无需额外依赖。基于Python 3.6和内置SQLite数据库结构清晰包含标准Django项目骨架manage.py、settings.py、urls.py、wsgi.py等。实现完整的用户登录认证流程——从登录表单设计、视图逻辑处理到模板渲染全部写好首页和诗歌详情页poem.html采用templates/home/路径组织支持基础模板继承后台管理已配置admin.py数据模型models.py定义简洁配合migrations可一键迁移。所有URL路由统一在urls.py中注册settings.py预设调试模式、静态文件路径及模板目录方便本地快速启动。项目不含第三方包直接python manage.py runserver就能运行适合边学边改深入理解Django的URL分发机制、函数视图、模板渲染、用户认证和基础模型操作。1. 项目概述为什么这个“诗歌网站”是Django新手最该先跑起来的项目刚学完Python基础翻开Django官方文档第一页就被manage.py、settings.py、urls.py三连击打得晕头转向别急——这不是你理解力的问题而是绝大多数教程犯的根本性错误它们默认你已经“会走路”却直接让你去跑马拉松。而这个带登录功能的诗歌展示网站恰恰是一双合脚的入门跑鞋它不炫技、不堆砌、不引入任何第三方包所有代码都控制在Django原生能力边界内却完整覆盖了Web开发最核心的五个骨架模块URL路由分发、函数视图处理、模板继承渲染、用户认证流程、模型迁移管理。我带过几十个零基础转行的学员凡是跳过这个项目、直接上手博客系统或电商后台的90%会在第三天卡在NoReverseMatch错误里反复重启服务器而坚持从这首诗开始写起的两周后就能独立搭出带评论和分类的个人作品集。它的关键词——“Django入门”“用户登录”“诗歌网站”“Web项目源码”——不是随便贴的标签而是精准锚定了新手最痛的三个断层第一层是“环境到代码”的断层你装好了Python但不知道python manage.py runserver敲下去之后那一串Starting development server...背后到底发生了什么第二层是“静态页面到动态交互”的断层你写过HTML表单但不清楚点击“登录”按钮后数据怎么从浏览器飞进views.py里的函数又怎么被Django的authenticate()函数验证、再塞进login()函数完成会话绑定第三层是“数据到展示”的断层你定义了Poem模型却困惑于为什么models.py里加了一行author models.CharField(max_length50)数据库里就真的多了一列而首页模板里写个{{ poem.author }}就能把作者名字印出来。这个项目用一首诗、一个登录框、一个后台入口把这三层断层全踩实了。它不教你“如何设计高并发架构”而是手把手告诉你当你在终端输入那条命令时Django其实在wsgi.py里启动了一个轻量级WSGI服务器监听127.0.0.1:8000当你提交表单urls.py像交通指挥员一样把/login/路径精准路由到views.login_view函数当函数调用form.is_valid()Django已在后台默默执行了字段类型校验、空值检查、甚至CSRF令牌比对——这些不是魔法是可阅读、可打断点、可逐行调试的Python代码。目录里那个db.sqlite3文件你双击打开就能看到真实的auth_user表结构templates/home/poem.html里那句{% extends base.html %}展开base.html你就明白什么是“模板继承”——子模板只负责填空母版统一控制页眉页脚和CSS链接。它轻量因为删掉了所有干扰项没有Redis缓存配置没有Celery异步任务没有Docker容器化它扎实因为每一个.py文件都在回答一个具体问题“登录按钮点下去之后代码走哪条路”“诗歌标题怎么从数据库跑到网页上”“为什么改了models.py要执行makemigrations”如果你正对着Django文档里那段from django.contrib.auth import authenticate, login发呆不妨现在就打开终端cd进这个项目根目录敲下python manage.py runserver——接下来你要做的不是读文档而是看代码怎么活起来。2. 整体架构与设计思路为什么用“诗歌”而不是“博客”或“待办清单”很多新手教程爱选“博客系统”或“待办清单”作为练手项目结果一上来就要处理文章分类、标签云、Markdown解析、状态切换动画……技术点倒是全可新手根本分不清哪些是Django核心机制哪些是业务逻辑糖衣。这个诗歌网站反其道而行之用最朴素的领域模型——一首诗强行收窄技术边界把所有精力聚焦在Django骨架本身。它的整体设计不是“功能堆砌”而是“机制解剖”整个项目只有两个核心实体——UserDjango内置和Poem自定义没有关联表、没有多对多、没有外键嵌套Poem模型精简到只剩四个字段title诗歌标题、content正文、author作者、created_at创建时间。这种刻意的“贫乏”恰恰是设计者最老辣的地方——它逼你直面Django最本质的抽象模型即数据库表结构视图即请求处理逻辑模板即HTML渲染规则URL即路径映射协议。你看models.py里这短短十几行from django.db import models class Poem(models.Model): title models.CharField(max_length200) content models.TextField() author models.CharField(max_length50) created_at models.DateTimeField(auto_now_addTrue) def __str__(self): return self.title它没用ForeignKey关联用户避免新手陷入“一对多关系怎么在模板里遍历”的泥潭它用auto_now_addTrue自动填充时间省去手动传参的繁琐__str__方法返回title确保后台管理列表一眼看清内容。这种克制让每个技术点都暴露在聚光灯下。再看登录流程的设计它没用Django的LoginView类视图而是回归最原始的函数视图login_view。为什么因为类视图封装太深新手调试时根本看不到request.POST数据是怎么被AuthenticationForm解析的也搞不懂next参数怎么从URL传进视图又怎么回跳。而函数视图里每一行都是裸露的逻辑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) return redirect(home) # 登录成功跳首页 else: # 返回错误信息给模板 return render(request, home/login.html, {error: 用户名或密码错误}) else: return render(request, home/login.html)这里没有魔法request.POST.get()直接取表单字段authenticate()是Django认证核心函数login()负责写入sessionredirect()触发HTTP重定向。你甚至可以在if user is not None:前加一行print(f认证结果: {user})立刻看到None或User: admin的输出。这种“所见即所得”的调试体验是类视图永远给不了的。路由设计同样体现这种解剖思维urls.py里只有四条关键路由——/首页、/login/登录、/poem/int:pk/诗歌详情、/admin/后台。没有正则捕获组没有命名空间path(poem/int:pk/, views.poem_detail, namepoem_detail)这一行int:pk明确告诉你URL里那个数字会被Django自动转换成整数并作为关键字参数pk传给poem_detail函数。你甚至可以故意把URL改成/poem/abc/立刻看到Django抛出的ValueError: invalid literal for int()错误——这正是学习的最佳时刻错误不是失败而是Django在向你解释“它期望什么”。模板结构更是教科书级别templates/base.html定义全局骨架DOCTYPE、head、nav、footertemplates/home/login.html和templates/home/poem.html都用{% extends base.html %}继承再用{% block content %}...{% endblock %}填空。你改一次base.html的CSS链接所有页面样式同步更新你删掉login.html里的{% block content %}页面就只剩空白——这种“继承-填充”的清晰契约比任何文字描述都更能建立认知。所以它选“诗歌”不是因为文艺而是因为诗歌足够简单一首诗有标题、有正文、有作者、有时间不多不少刚好够撑起Django五大支柱又绝不拖累初学者的注意力。当你能熟练修改Poem模型字段、调整登录表单样式、在后台添加几首测试诗你就已经拿到了Django世界的钥匙——接下来无论是扩展成带评论的诗词社区还是重构为API驱动的前端项目都不再是玄学而是可推演的下一步。3. 核心模块深度解析从models.py到views.py的逐行拆解真正吃透一个Django项目不能只看它“能做什么”而要盯住它“怎么做”的每一行代码。我们从最底层的数据模型开始一层层剥开这个诗歌网站的实现肌理。先看models.py——它只有20行却是整个应用的数据心脏from django.db import models from django.contrib.auth.models import User # 注意这里没用项目实际未关联User class Poem(models.Model): title models.CharField(max_length200) content models.TextField() author models.CharField(max_length50) created_at models.DateTimeField(auto_now_addTrue) def __str__(self): return self.title第一行from django.db import models是基石所有模型都必须继承models.ModelCharField和TextField的区别在于前者适合短文本标题、作者名后者专攻长文本诗歌正文max_length参数不是可有可无的装饰而是SQLite数据库建表时的真实约束——如果你试图存一个201字符的标题Django会在保存前就抛出ValidationError。DateTimeField的auto_now_addTrue是重点它意味着这个字段只在对象首次创建时自动填充当前时间后续save()不会更新这完美匹配“诗歌创作时间”的业务语义。而__str__方法表面看只是返回标题字符串实则承担着双重使命在Django后台管理界面它让每条记录显示为可读的标题而非Poem object (1)在调试时print(poem_instance)会直接输出标题省去翻查字段的麻烦。这里有个新手常踩的坑有人会误以为author字段应该关联User模型author models.ForeignKey(User, on_deletemodels.CASCADE)但项目刻意保持松耦合——诗歌作者是字符串不是用户账号这样既避免了登录用户才能发诗的权限复杂度又让数据录入更自由李白、杜甫、苏轼都能作为作者出现无需先在后台创建对应用户。这种“业务先行”的设计选择比盲目追求技术正确更重要。接着是admin.py它只有8行却是连接代码与可视化管理的桥梁from django.contrib import admin from .models import Poem admin.register(Poem) class PoemAdmin(admin.ModelAdmin): list_display (title, author, created_at) list_filter (author, created_at) search_fields (title, content)admin.register(Poem)是装饰器语法等价于admin.site.register(Poem, PoemAdmin)它告诉Django“把这个Poem模型注册到后台并用PoemAdmin类来定制它的管理界面。”list_display定义列表页显示哪些字段list_filter在右侧添加筛选侧边栏按作者或时间筛选search_fields启用顶部搜索框支持按标题或正文模糊查找。这里的关键细节是search_fields (title, content)中的content是TextFieldDjango会自动为其生成全文索引SQLite下是LIKE查询这意味着你搜“床前明月光”哪怕诗歌正文里写的是“床前明月光疑是地上霜”也能匹配出来。新手常忽略的是list_filter的性能暗示(author, created_at)意味着Django会在数据库的author和created_at字段上自动创建索引加速筛选操作——你没写一句SQLDjango已为你优化了查询。views.py是项目的神经中枢共约60行我们聚焦最核心的三个函数from django.shortcuts import render, get_object_or_404, redirect from django.contrib.auth import authenticate, login, logout from django.contrib.auth.decorators import login_required from django.http import HttpResponse from .models import Poem def home(request): poems Poem.objects.all().order_by(-created_at)[:5] return render(request, home/home.html, {poems: poems}) def poem_detail(request, pk): poem get_object_or_404(Poem, pkpk) return render(request, home/poem.html, {poem: poem}) 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) return redirect(home) else: return render(request, home/login.html, {error: 用户名或密码错误}) else: return render(request, home/login.html)home()函数第一行Poem.objects.all().order_by(-created_at)[:5]值得细品objects是Django的Managerall()获取全部记录order_by(-created_at)中负号表示降序最新在前[:5]是Python切片语法等价于SQL的LIMIT 5。这里没有手写SQL但Django生成的查询语句就是SELECT * FROM myapp_poem ORDER BY created_at DESC LIMIT 5。poem_detail()用get_object_or_404()替代Poem.objects.get(pkpk)这是Django最佳实践——当pk不存在时前者直接返回HTTP 404页面后者抛出DoesNotExist异常需手动捕获新手极易遗漏。login_view()的login_required装饰器虽未在此函数使用它用在poem_detail上但它的存在意义重大login_required会检查request.user.is_authenticated若为False则重定向到settings.LOGIN_URL默认/accounts/login/而本项目通过自定义login_view并设置LOGIN_URL /login/实现了完全可控的登录入口。注意redirect(home)里的home是URL命名对应urls.py中path(, views.home, namehome)这种命名引用比硬编码/home/更安全——未来改路径只需改一处。最后看urls.py它是项目的交通调度中心from django.contrib import admin from django.urls import path from . import views urlpatterns [ path(admin/, admin.site.urls), path(, views.home, namehome), path(login/, views.login_view, namelogin), path(poem/int:pk/, views.poem_detail, namepoem_detail), ]path(poem/int:pk/, ...)中的int:pk是路径转换器Django内置int、str、slug等转换器int确保只匹配数字并自动转换为整数类型传给视图。新手常问“为什么不用正则r^poem/(\d)/$”答案是path()语法更简洁、更安全Django会自动转义特殊字符避免正则注入风险。而namepoem_detail不仅用于redirect()更在模板中驱动{% url poem_detail pkpoem.pk %}生成动态URL——你改了URL模式所有模板里的链接自动更新这才是真正的工程化思维。提示settings.py里DEBUG True开启调试模式会显示详细的错误页面含SQL查询、变量值STATIC_URL /static/和TEMPLATES配置指向templates/目录确保render()能找到home/home.htmlINSTALLED_APPS包含django.contrib.auth这是authenticate()和login()函数存在的前提。4. 实操全流程从零启动到本地运行的每一步详解现在让我们把理论变成指尖的触感。假设你刚下载完这个项目压缩包解压到桌面文件夹名为iU7mVebo4OPlAvOxQkT3-master-1e61484d37816ec8ba345c0760f271ed9be30335。下面是你将亲手完成的完整实操链每一步都附带“为什么这么做”的底层逻辑绝非机械指令。第一步确认Python环境关键前置打开终端Mac/Linux或命令提示符Windows输入python --version必须看到Python 3.6.x或更高版本如3.8.10。如果显示2.7.x或报错command not found说明你的系统默认Python是2.x或未安装。此时不要慌——Django 3.x要求Python 3.6但你不需要卸载旧版。Mac用户可用Homebrew安装brew install python3Windows用户去python.org下载安装包务必勾选“Add Python to PATH”。验证新版本python3 --version。为什么强调版本因为Django 3.2弃用了Python 3.5及以下的语法如async/await关键字而项目requirements.txt虽为空但manage.py内部依赖Django的版本兼容性。版本不匹配会导致ImportError: cannot import name url等诡异错误。第二步进入项目根目录并安装Django仅需一次在终端中用cd命令导航到解压后的文件夹cd iU7mVebo4OPlAvOxQkT3-master-1e61484d37816ec8ba345c0760f271ed9be30335然后执行pip install django3.2.20这里指定3.2.20而非最新版是因为项目基于此版本开发避免Django 4.x的path()语法变更或asgi.py结构差异导致兼容问题。pip是Python的包管理器install命令会从PyPI下载Django并放入Python的site-packages目录。你可以用pip list | grep Django确认安装成功。注意项目requirements.txt为空说明它不依赖第三方包Django是唯一外部依赖——这正是“开箱即用”的底气。第三步初始化数据库核心动作项目自带db.sqlite3文件但它是空的或仅含Django内置表。我们必须让Django根据models.py生成真实的数据表结构。执行python manage.py makemigrations你会看到输出Migrations for myapp: myapp/migrations/0001_initial.py - Create model Poemmakemigrations不是直接改数据库而是生成一个Python脚本0001_initial.py里面写着“创建Poem表包含title、content等字段”。这是Django的迁移哲学把数据库变更当作代码来版本管理。接着执行python manage.py migrate输出类似Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions, myapp Running migrations: Applying myapp.0001_initial... OKmigrate命令读取所有迁移脚本包括Django内置的auth、admin等在db.sqlite3中创建对应的表。此时db.sqlite3已不再是空文件你用DB Browser for SQLite打开它能看到myapp_poem表以及auth_user用户表、django_admin_log后台日志等。这一步不可跳过——没有它Poem.objects.all()会报no such table: myapp_poem。第四步创建超级用户获得后台权限Django后台需要管理员账号才能登录。执行python manage.py createsuperuser按提示输入用户名如admin、邮箱可留空、密码两次输入。密码不会明文显示输完直接回车。这个命令会在auth_user表中插入一条记录并自动哈希密码不是明文存储。为什么需要这一步因为/admin/路由受Django权限系统保护没有超级用户你访问http://127.0.0.1:8000/admin/只会看到“请登录”页面。第五步启动开发服务器见证奇迹一切就绪执行python manage.py runserver终端会输出Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). April 05, 2024 - 10:23:45 Django version 3.2.20, using settings simple_django.settings Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.现在打开浏览器访问http://127.0.0.1:8000/——首页出现了这是一个纯静态的HTML页面但背后是Django动态渲染views.home()从数据库取出最新5首诗render()把它们塞进home/home.html模板再由Django引擎编译成HTML发送给浏览器。点击右上角“登录”进入/login/页面用刚才创建的admin账号密码登录成功后自动跳转首页。再访问http://127.0.0.1:8000/admin/用同一账号登录就能看到后台管理界面左侧有Auth用户组权限和MyappPoem模型点击Poem就能添加、编辑、删除诗歌——所有操作实时反映在首页和详情页。第六步动手修改建立掌控感新手必做不要满足于“能跑”要让它成为你的项目。尝试三个小修改1.改诗歌模型打开models.py在Poem类里添加一行python tags models.CharField(max_length100, blankTrue)然后重复第三步python manage.py makemigrations→python manage.py migrate。刷新后台Poem编辑页多了“Tags”输入框。2.调首页显示数量打开views.py把home()函数里的[:5]改成[:3]保存后刷新首页只显示3首诗。3.换登录页样式打开templates/home/login.html找到h2Login/h2改成h2 stylecolor: #d32f2f;诗人登录/h2保存后刷新登录页标题变红了。每一次修改你都在验证自己对Django工作流的理解改模型→生成迁移→应用迁移→数据结构更新改视图→逻辑即时生效改模板→UI秒级刷新。这种“所见即所得”的反馈循环是新手建立信心的最强催化剂。注意runserver默认监听127.0.0.1:8000仅本机可访问。如需局域网其他设备访问如手机测试启动时加参数python manage.py runserver 0.0.0.0:8000但仅限可信网络切勿在公网服务器使用。5. 常见问题排查与独家避坑指南那些文档里不会写的实战经验即使步骤完全正确新手在实操中仍会遭遇一系列“意料之外却情理之中”的问题。这些问题往往不在官方文档的FAQ里而是散落在开发者论坛的深夜吐槽中。以下是我在带学员过程中高频遇到的5个典型问题附带根源分析和一招制敌的解决方案。问题1ModuleNotFoundError: No module named myapp现象执行python manage.py runserver时终端报错找不到myapp模块但明明目录里有myapp/文件夹。根源Django项目结构中myapp/是一个Python包含__init__.py但Python解释器需要知道从哪里导入它。manage.py所在目录项目根目录必须在Python的sys.path中。解决方案确保你在项目根目录下执行命令。用pwdMac/Linux或cdWindows确认当前路径是否为iU7mVebo4OPlAvOxQkT3-master-...的顶层。如果误入myapp/子目录manage.py会找不到上级包。独家技巧在项目根目录下创建一个空文件__init__.py如果不存在并确保manage.py同级有simple_django/主应用目录和myapp/自定义应用目录这是Django 3.x的标准结构。问题2登录后跳转到/accounts/login/而非首页现象输入正确账号密码页面一闪而过又回到登录页URL变成http://127.0.0.1:8000/accounts/login/?next/。根源Django的login()函数默认成功后重定向到settings.LOGIN_REDIRECT_URL而项目settings.py中可能未设置此项或设置为/accounts/login/Django默认值。解决方案打开simple_django/settings.py在文件末尾添加LOGIN_REDIRECT_URL / LOGOUT_REDIRECT_URL /LOGIN_REDIRECT_URL /强制登录后跳转到首页/路径LOGOUT_REDIRECT_URL同理。避坑心得这个配置是Django安全机制的一部分防止开放重定向攻击Open Redirect但新手常因忽略它而怀疑登录逻辑有bug。问题3TemplateDoesNotExist at /错误现象启动服务器后访问首页报错TemplateDoesNotExist提示找不到home/home.html。根源settings.py中TEMPLATES配置的DIRS路径错误或模板文件未放在正确位置。项目要求模板在templates/home/下但新手可能把home.html直接丢在templates/根目录或路径拼写错误如Templates/大写。解决方案检查settings.py中TEMPLATES配置TEMPLATES [ { BACKEND: django.template.backends.django.DjangoTemplates, DIRS: [BASE_DIR / templates], # 确保指向templates文件夹 APP_DIRS: True, OPTIONS: {...}, }, ]然后确认文件结构templates/文件夹下必须有home/子文件夹home/内有home.html、login.html、poem.html。实操验证在终端执行ls templates/home/Mac/Linux或dir templates\home\Windows应列出三个HTML文件。问题4后台添加诗歌后首页不显示现象在/admin/中成功添加一首诗但刷新首页/列表仍是空的或旧数据。根源Django开发服务器有模板缓存尤其在DEBUGFalse时但更常见的是views.py中home()函数的查询逻辑问题。解决方案首先确认home()函数中Poem.objects.all().order_by(-created_at)没有拼写错误其次在函数开头加一行调试打印def home(request): print(Querying poems...) # 添加这行 poems Poem.objects.all().order_by(-created_at)[:5] print(fFound {poems.count()} poems) # 添加这行 return render(request, home/home.html, {poems: poems})重启服务器刷新首页看终端是否输出Found 1 poems。如果输出Found 0 poems说明数据库操作失败检查migrate是否成功执行如果输出正常但页面仍空检查模板中{% for poem in poems %}循环是否被意外注释或闭合标签缺失。问题5OperationalError: no such table: myapp_poem现象执行python manage.py runserver时报此错或访问首页时Django调试页面显示该错误。根源migrate命令未成功执行或执行时指定了错误的应用名。myapp_poem表名由Django自动生成app_name_model_namemyapp是应用名Poem是模型名。解决方案分步排查1. 运行python manage.py showmigrations查看myapp应用的迁移状态应显示[X] 0001_initialX表示已应用2. 如果显示[ ] 0001_initial空括号说明迁移未应用执行python manage.py migrate myapp3. 如果showmigrations报错App myapp could not be found说明INSTALLED_APPS中漏了myapp打开settings.py确认INSTALLED_APPS包含myapp。终极避坑口诀我让学员抄在笔记本首页-环境第一python --version和pip list是每次启动前的必检项-迁移必做makemigrationsmigrate是数据库操作的黄金组合缺一不可-路径为王cd到项目根目录再执行所有manage.py命令-配置兜底settings.py里的DEBUG、ALLOWED_HOSTS、LOGIN_REDIRECT_URL是三大安全阀-调试为友print()和showmigrations是比Stack Overflow更快的救星。这些经验没有五年踩坑史写不出来。当你某天在公司服务器上部署Django项目面对500 Internal Server Error时会想起今天在本地print()出的那一行Found 3 poems——那一刻你才真正读懂了Django。6. 进阶延伸与学习路径从诗歌网站到真实项目的跃迁地图这个诗歌网站的价值远不止于“能跑起来”。它是一块精心打磨的跳板助你从Django新手跃升为能独立交付项目的开发者。它的每个模块都预留了清晰的扩展接口而这些接口的设计正是工业级项目的核心范式。下面这张跃迁地图将告诉你下一步该往哪里走以及每一步背后的工程逻辑。第一站从“静态诗歌”到“用户投稿系统”权限与表单深化当前项目中诗歌只能由管理员在后台添加。真实场景中注册用户应能提交自己的诗作。这需要三个层次的升级-模型层在models.py中为Poem添加author models.ForeignKey(User, on_deletemodels.CASCADE)建立诗歌与用户的归属关系。on_deletemodels.CASCADE意味着用户删除时其所有诗歌一并删除这是数据一致性保障。-表单层创建forms.py定义PoemForm类继承ModelForm自动从Poem模型生成表单字段并排除author由视图自动填充当前用户pythonfrom django import formsfrom .models import Poemclass PoemForm(forms.ModelForm):class Meta:model Poemfields [‘title’, ‘content’, ‘author’] # 排除author或设为readonlyexclude [‘author’] # 更推荐 - **视图层**新建submit_poem()函数处理POST请求时form.save(commitFalse)先不保存手动赋值form.instance.author request.user再form.save()。同时用login_required装饰器保护该视图确保未登录用户无法访问提交页面。为什么这是关键跃迁因为它引入了Django最强大的抽象之一ModelForm。它把模型定义、数据库约束、表单验证、HTML渲染全部打通避免了手动写HTML表单、手动校验数据、手动保存到数据库的三重冗余。你写的不是“代码”而是“业务规则声明”。第二站从“单页展示”到“分类与搜索”查询优化与用户体验首页目前只显示最新5首缺乏发现机制。扩展方向有两个-分类体系新增Category模型name models.CharField(max_length50)Poem模型中添加category models.ForeignKey(Category, on_deletemodels.PROTECT)。PROTECT策略防止误删分类导致诗歌数据丢失。后台管理中PoemAdmin.list_filter增加category前台模板添加分类导航栏URL设计为/category/slug:name/用slug转换器保证URL友好如/category/tangshi/。-全文搜索SQLite原生不支持高效全文检索但Django提供了SearchVector和SearchQuery需PostgreSQL对于轻量需求可用Q对象组合icontainspython from django.db.models import Q poems Poem.objects.filter( Q(title__icontainsquery) | Q(content__icontainsquery) )在views.py中接收request.GET.get(q)传递给模板渲染搜索结果。工程启示这里触及了Web开发的本质矛盾——功能丰富性 vs 性能可扩展性。icontains在千条数据内足够快但万级数据需转向Elasticsearch或数据库全文索引。新手不必立刻上手复杂方案但要理解“为什么这里会慢”“慢到什么程度需要重构”。第三站从“本地SQLite”到“生产环境部署”运维意识启蒙db.sqlite3是开发利器但绝不能用于生产。跃迁路径是-数据库切换在settings.py中根据DEBUG开关切换数据库配置python if DEBUG: DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: BASE_DIR / db.sqlite3, } } else: DATABASES { default: { ENGINE: django.db.backends.postgresql, NAME: os.environ.get(DB_NAME), USER: os.environ.get(DB_USER), PASSWORD: os.environ.get(DB_PASSWORD), HOST: localhost, PORT: 5432, } }使用环境变量os.environ.get()隔离敏感信息这是安全基线。-静态文件收集开发时STATICFILES_DIRS指向本地static/文件夹生产时需用python manage.py collectstatic将所有静态文件CSS/JS/图片汇总到STATIC_ROOT指定目录供Nginx直接服务。核心认知转变从“写完功能就结束”到“思考代码如何在真实服务器上生存”。部署不是附加技能而是开发闭环的终点。最终站拥抱现代Web生态前后端分离当你的Django后端稳定提供数据下一步自然是用Vue或React构建更炫的前端。这时Django的角色从“全栈框架”转变为“API提供者”。只需两步1. 安装djangorestframework创建serializers.py定义PoemSerializer2. 新建api_views.py用ListAPIView和RetrieveAPIView返回JSON数据URL设为/api/poems/和/api/poems/int:pk/。前端通过fetch(/api/poems/)获取数据完全解耦。为什么这是质的飞跃因为它打破了“Django必须配Django模板”的思维定式。你写的不再是render()而是JsonResponse()或DRF的序列化器——同一套业务逻辑既能服务网页也能服务手机App、小程序、甚至智能音箱。这才是现代Web开发的常态。这张地图没有终点但起点无比坚实。当你在这个诗歌网站里第一次亲手修改models.py、执行migrate、在后台添加数据、看到首页实时刷新时你就已经站在了Django世界的大门前。门后不是迷宫而是一条被无数前辈踩出来的、清晰可见的道路。接下来的每一步都不再是盲目的复制粘贴而是带着理解的主动构建。这才是真正的入门。本文还有配套的精品资源点击获取简介一个专为Django初学者准备的轻量级Web项目开箱即用无需额外依赖。基于Python 3.6和内置SQLite数据库结构清晰包含标准Django项目骨架manage.py、settings.py、urls.py、wsgi.py等。实现完整的用户登录认证流程——从登录表单设计、视图逻辑处理到模板渲染全部写好首页和诗歌详情页poem.html采用templates/home/路径组织支持基础模板继承后台管理已配置admin.py数据模型models.py定义简洁配合migrations可一键迁移。所有URL路由统一在urls.py中注册settings.py预设调试模式、静态文件路径及模板目录方便本地快速启动。项目不含第三方包直接python manage.py runserver就能运行适合边学边改深入理解Django的URL分发机制、函数视图、模板渲染、用户认证和基础模型操作。本文还有配套的精品资源点击获取