新闻详情

新闻详情

首页 / 资讯中心 / 详情

Django全栈博客开发实战:从模型设计到登录权限的完整指南

发布时间:2026/10/2 3:44:39来源:尧图网络
Django全栈博客开发实战:从模型设计到登录权限的完整指南
最近一个朋友问我新人学 Django 到底该怎么下手我直接把他拉到了我写了大半年的博客系统代码仓库前。这个项目既是我的练手作品也是我接触全栈开发的起点博客系统刚好覆盖了前端页面、后端接口、数据库建模、用户登录、权限控制这些核心环节规模又不至于大到劝退。如果你也想找一条“能跑通、能分享、能积累实战经验”的入门路径对着这个项目一步步敲会比刷十遍教程都管用。我在这里就把整个博客系统从项目设计到最终上线前的关键节点完整拆一遍包括技术选型、数据库模型、ORM 的增删改查、登录功能实现还有新手最容易栽进去的坑。所有代码细节都是我在实际操作里验证过的你照着做就能复现一套能用的博客。1. 项目设计与搭建准备1.1 为什么选 Django 做博客系统选择 Django 不是因为它是最新潮的框架而是因为它把全栈开发里最琐碎的部分替你料理好了。对比过 Flask、Express 这类轻量框架后你会发现博客系统需要的用户认证、后台管理、数据库迁移、表单处理几乎每一项都得自己搭配第三方库而 Django 自带全套。用一句话概括Django 是一个“自带电池”的框架它默认给你组装好了脚手架你只需要专注业务逻辑本身。具体到博客系统Django 自带的 Admin 后台可以让你在几个小时之内拥有一个可管理文章、用户、分类的可视化界面这在项目早期价值巨大。而且它的 ORM 屏蔽了不同数据库之间的差异无论是开发阶段的 SQLite 还是部署后的 PostgreSQL改一行配置就能切换。很多人说 Django 笨重但对新手来说这种“约束”反而是保护你不需要纠结发送邮件选哪个库、做分页要不要引入第三方包框架已经帮你选好了最常见的方案。1.2 本地环境与项目骨架搭建我用的环境是 Python 3.10 和 Django 4.2 LTS选 LTS 版本是因为它维护周期长社区资料也最丰富。建议你先用虚拟环境隔离依赖别图省事直接装到全局python -m venv venv source venv/bin/activate # Windows 下执行 venv\Scripts\activate pip install Django4.2.* django-admin startproject myblog cd myblog python manage.py startapp blog python manage.py runserver执行完startproject后项目根目录会生成manage.py、myblog/settings.py、myblog/urls.py等文件startapp blog则创建了业务逻辑所在的 app。我习惯把项目配置和应用模块分开放这样以后如果博客要加评论、加订阅号功能直接新建 app 扩展就行不用把代码都堆在同一个文件里。起步阶段有一个非常容易被忽视的配置settings.py里的ALLOWED_HOSTS。本地调试可以留空但如果后面你想用手机在同一局域网下访问或者在部署后通过域名访问必须把宿主地址加进去否则 Django 会直接拒绝请求并报DisallowedHost。我第一次部署到服务器时在这上面卡了快一个小时其实就是少加了一个域名。数据库方面开发阶段直接使用默认的 SQLite 就可以。它不需要额外安装服务数据也存在一个本地文件里非常适合学习和单机部署。生产环境我会换到 PostgreSQL但这不影响业务代码Django 的 ORM 把这个差异完全抹平了。真正要留心的是在跑任何数据库操作前先执行python manage.py makemigrations python manage.py migrate新手最容易急着写模型却忘了生成并执行迁移文件结果后端一运行就报no such table。顺带一提migrate会自动创建 Django 内置的用户表、会话表等基础数据表这也是为什么我总说这个框架“自带电池”。2. 核心模型设计与用户体系2.1 博客文章模型设计一个博客系统的数据模型不必复杂但每个字段都要想清楚用途。我设计的Post模型如下from django.db import models from django.contrib.auth.models import User from django.utils import timezone from django.urls import reverse class Category(models.Model): name models.CharField(max_length50, uniqueTrue) def __str__(self): return self.name class Tag(models.Model): name models.CharField(max_length30, uniqueTrue) def __str__(self): return self.name class Post(models.Model): STATUS_CHOICES [ (draft, 草稿), (published, 已发布), (trash, 回收站), ] title models.CharField(标题, max_length200) slug models.SlugField(URL别名, max_length250, uniqueTrue) author models.ForeignKey(User, on_deletemodels.CASCADE, verbose_name作者) category models.ForeignKey(Category, on_deletemodels.SET_NULL, nullTrue, blankTrue, verbose_name分类) tags models.ManyToManyField(Tag, blankTrue, verbose_name标签) summary models.TextField(摘要, max_length500, blankTrue) content models.TextField(正文) status models.CharField(状态, max_length10, choicesSTATUS_CHOICES, defaultdraft) views models.PositiveIntegerField(浏览量, default0) created_at models.DateTimeField(创建时间, defaulttimezone.now) updated_at models.DateTimeField(更新时间, auto_nowTrue) class Meta: ordering [-created_at] def __str__(self): return self.title def get_absolute_url(self): return reverse(blog:post_detail, args[self.slug])重点说几个设计细节。slug字段用于生成文章详情页的 URL比如https://example.com/post/django-intro/它比?id1更利于 SEO也让分享链接更可读。你可能发现我把slug设成uniqueTrue这意味着标题一旦确定后再改 URL 会造成链接失效所以我在后台表单里让用户手动维护这个字段而不是自动生成内容编辑多了你就会知道这个“麻烦”换来了多大的可控性。status字段是博客系统内容管理的关键。我的热词里有“小修系统博客”这类词其实说的就是后台维护场景文章不必一写完就发布可以先存草稿等配图、校对完成后再改成“已发布”。回收站状态则避免了误删后无法恢复的尴尬。views字段用来统计浏览量。很多初学者会在这里踩坑每次刷新页面就在视图里执行post.views 1然后save()这种做法不仅会有并发覆盖问题还会在每次请求时多写一次数据库。推荐的做法是用 Django 的F()表达式from django.db.models import F Post.objects.filter(pkpost.pk).update(viewsF(views) 1)这行 SQL 是在数据库层面原子完成的不会因为两个用户同时访问而丢失更新。2.2 用户模型与认证体系用户模块我直接使用了 Django 自带的auth.User没有自己重写UserModel。原因很简单博客需要的登录、密码加密、权限分组Django 全都已经实现了。对新手来说自定义用户模型的坑很多——比如改到一半迁移历史乱七八糟、外键指向出错不如先用官方默认方案。文章和用户的关联用的是models.ForeignKey(User, on_deletemodels.CASCADE)。CASCADE意味着如果删除了某个作者他写的文章也会一起删除。实际运营博客时这可能不是你想要的行为你更希望保留文章只是作者显示成“已注销用户”。我第二次重构时改成了on_deletemodels.SET_NULL并配合nullTrue这样即便作者账号删除文章记录依然存在。这个取舍建议你在写之外都考虑清楚因为一旦上线修改关联策略涉及的迁移和数据维护成本不小。登录页面我用的是类视图LoginView配合自定义模板。Django 默认的认证视图已经把“验证账号密码、写入 session、跳转下一页面”整套流程封装好了你只需要在urls.py里指一下模板位置from django.contrib.auth import views as auth_views urlpatterns [ path(login/, auth_views.LoginView.as_view(template_nameregistration/login.html), namelogin), path(logout/, auth_views.LogoutView.as_view(), namelogout), ]之所以用内置视图是因为它内部处理了next参数——用户未登录访问受限页面时会自动跳转登录页登录成功后再回到原本想看的页面。换成自己手写登录逻辑时这个细节非常容易漏掉。2.3 用 Django Unfold 提升后台管理水平默认的 Django Admin 长得很“极简”对新人来说谈不上好用但绝对够用。后来我在打磨时加了django-unfold这个主题插件配合pip install django-unfold和INSTALLED_APPS配置几行代码就能把后台变成现代一点的界面风格INSTALLED_APPS [ unfold, unfold.contrib.filters, unfold.contrib.forms, django.contrib.admin, # ... ]这里要特别强调unfold必须放在django.contrib.admin之前否则主题无法覆盖默认模板。很多人照着文档配完发现没变化十有八九是安装顺序错了。Unfold 带来的不只是外观改善它还把筛选、搜索、导出等操作集成得更好。博客后台每天要处理几十篇文章时这种操作效率的提升是非常直观的。3. 博客系统的查询、删除与 ORM 细节3.1 文章列表与查询集优化博客首页通常要展示已发布的文章列表并按时间倒序排列。ORM 里的对应写法是posts Post.objects.filter(statuspublished).select_related(author, category).prefetch_related(tags)select_related和prefetch_related是 Django ORM 里最值得学习的两个方法。理解它们的重点在于“减少数据库查询次数”。如果不加这两句每循环一篇文章取作者时都要执行一次 SQL首页 10 篇文章就要多出 10 次查询这就是典型的 N1 问题。加了之后Django 会用一次 JOIN 把作者和分类查出来通常能省掉大半查询时间。如果文章数量大分页也是必须的。我用的不是自己手写的页码逻辑而是内置Paginatorfrom django.core.paginator import Paginator paginator Paginator(post_list, 10) page_obj paginator.get_page(request.GET.get(page))get_page的好处是页码越界时它不会抛异常而是自动给出最后一页或第一页对用户友好得多。3.2 创建、更新与删除对象的正确姿势热词里反复出现了“django 执行查询-删除对象”我也把这一块单独拿出来讲因为这是新手面向数据库操作最容易出问题的地方。创建对象可以用create()也可以用objects.create()post Post.objects.create( title我的第一篇博客, slugmy-first-blog, authorrequest.user, contentHello world, statuspublished, )更新则建议用update而不是先查出对象再save()。区别在于queryset.update()只执行一条 UPDATE 语句不会触发每个实例的save()方法性能更好但要注意它也不会自动更新auto_now字段和信号所以在更新内容时我会用save()在批量更新浏览量时用update()。删除操作最值得警惕post Post.objects.get(slugmy-first-blog) post.delete()上面这段代码会把文章从数据库里永久移除。Django 的delete()是级联删除也就是说如果文章下面挂着评论、图片它们也会一并被删除而且这个过程不可逆。我最初做博客时不小心把一篇文章删掉才发现关联的评论全没了当时就意识到“物理删除”对内容型系统来说有多危险。更稳妥的方案是“逻辑删除”也就是把status改成trash保留数据但不在前台渲染。实现起来就是在列表页的查询条件里加一个exclude(statustrash)。回收站功能不是“多此一举”而是内容管理系统的底线保障。3.3 关联对象删除策略与回收站的实现回到外键on_delete参数Django 支持多个策略策略行为适用场景CASCADE父对象删除时子对象一起删帖子与评论、订单与明细SET_NULL父对象删除时子对象外键置空文章作者注销后保留文章PROTECT有子对象引用时禁止删除父对象分类下有文章时阻止删除分类SET_DEFAULT删除后设为默认值有默认外键的情况博客的文章和用户之间我最终选择了SET_NULL避免了一删作者文章全没的惨剧。分类用SET_NULL是因为一篇文章没有分类依然可以正常展示而评论和文章之间则保留CASCADE因为评论失去所属文章后毫无意义。回收站的查询实现很简单Post.objects.filter(statustrash)恢复时改回published即可。这套逻辑可以在 Admin 后台操作也可以写一个管理命令定期清空超过 30 天的回收站看你的具体需求。我在实际运营中发现保留“恢复”能力远比定期清空重要因为编辑常常是删完过两天又后悔。4. 登录功能与全栈闭环实现4.1 登录、登出与 Session 机制博客系统的登录功能看起来简单但背后牵扯的是 Django 的 Session 机制。用户提交账号密码后LoginView会校验用户信息校验通过就把用户 ID 加密写入服务端的 Session 表同时给浏览器下发一个sessionidCookie。之后的每次请求Django 都会用这个 Cookie 找到对应的 Session从而恢复出request.user。理解这个流程对排查登录失效问题很有帮助。比如很多人会遇到“登录后刷新又变回未登录”多半是浏览器禁用了 Cookie或者SESSION_COOKIE_SECURE配合非 HTTPS 环境导致 Cookie 没能写入。本地开发时别急着设SESSION_COOKIE_SECURETrue否则http://127.0.0.1:8000上登录永远无法保持。登出同样简单LogoutView会清掉服务端的 Session 数据。不过在实现时我故意没有用 “POST 跳转”而是设置了LOGIN_REDIRECT_URL和LOGOUT_REDIRECT_URLLOGIN_URL login LOGIN_REDIRECT_URL blog:post_list LOGOUT_REDIRECT_URL blog:post_list这里有个小细节Django 从某个版本开始将登出接口严格限制为 POST 方法如果你用某个教程里的老代码直接发 GET 请求会报 405。倒不是越改越难用只是应了那句老话——框架升级后你最少要扫一眼官方 release notes不然很多“旧写法”会莫名其妙失效。4.2 保护视图与登录要求博客的“创建文章”和“后台管理”页面不应该让未登录用户访问。靠模板里藏掉链接不够安全后端必须做权限校验。最简单的做法是加装饰器from django.contrib.auth.decorators import login_required from django.views.decorators.http import require_POST login_required def post_create(request): ... login_required require_POST def post_delete(request, slug): ...如果你要限定只有管理员is_staff能操作可以用staff_member_required。权限这块的原则是“后端兜底前端美化”前端隐藏操作按钮只为了用户体验真正的安全边界始终在后端视图和模型层。文章详情的浏览量统计也要考虑登录状态吗不需要views是公开数据登录与否只影响你能不能进入编辑页。我在模板里用了{% if user.is_authenticated %}判断是否显示“编辑”按钮但即便有人绕过前端直接构造 URL 访问编辑页后端没有login_required的视图照样会被拦截。4.3 模板继承与全栈页面串联博客的前端页面由模板、静态文件和 URL 路由共同构成。Django 的模板系统支持继承这是我搭建页面时最享受的一步先写一个base.html把导航栏、页脚、CSS 引用都放进去然后每个页面只需继承它并覆盖 content 块。!DOCTYPE html html langzh-hans head meta charsetUTF-8 title{% block title %}{% endblock %} - 我的博客/title /head body nav {% if user.is_authenticated %} p你好{{ user.username }}/p a href{% url logout %}退出/a {% else %} a href{% url login %}登录/a {% endif %} /nav main {% block content %}{% endblock %} /main /body /html文章详情页里展示正文和作者{% extends base.html %} {% block title %}{{ post.title }}{% endblock %} {% block content %} article h1{{ post.title }}/h1 p作者{{ post.author.username }} | 分类{{ post.category.name }} | 浏览 {{ post.views }}/p div{{ post.content|linebreaks }}/div /article {% endblock %}{% url %}标签是我反复强调要用的。它根据路由 name 动态生成 URL而不是直接硬编码/post/my-first-blog/。这样即使你调整了路由路径所有引用它的模板都会自动跟随不需要逐个改文件。静态文件处理方面开发阶段把 CSS、JS、图片放在全局static/目录并在配置里加入STATIC_URL static/ STATICFILES_DIRS [BASE_DIR / static]然后用{% load static %}在模板里引用。等到部署时再执行collectstatic收集所有静态文件交给 Nginx 处理。这个流程在全栈开发里属于“最后一公里”很多新手在本地一切正常一上线样式全丢就是因为忘了配置静态文件的对外服务路径。5. 常见问题排查与干货速查5.1 Django 全栈新手最容易踩的坑把项目从开发带到运行的过程中我统计过自己踩过的坑发现有几种是反复出现的。第一个是迁移混乱。我最初偷懒直接删了 SQLite 数据库文件来重置数据但后来发现migrations目录里的历史记录还在导致再执行migrate时出现“表已存在”之类的错。正确处理方式是用 Django 提供的方式创建迁移并重置而不是暴力删库。特别是多人协作场景下随意改迁移文件会让队友直接崩溃。第二个是没有给模型写__str__。Admin 后台列表默认展示Post object (1)根本看不出是哪篇文章。加上__str__之后后台立即变得人性化这个习惯要尽早养成。第三个是模板中跨过预取关系。比如在循环里写{{ post.author.blog_profile.bio }}每一行都可能触发额外的 SQL。虽然博客规模不大时看不出问题但一旦数据量上来页面响应会变得奇慢。排查这类问题最快的方式是安装 Django Debug Toolbar它能在页面底部显示所有 SQL 执行情况和耗时。第四个是DEBUGFalse后静态文件和服务突然“失效”。生产环境里 Django 不会自动帮你托管静态文件这部分要交给 Nginx。如果你还没有部署 Nginx也可以临时用python manage.py runserver --insecure客串一下但仅供测试不要拿来长时间对外服务性能和安全都靠不住。5.2 登录和权限相关报错速查结合我做登录和权限时踩过的坑整理一个速查表现象可能原因解决办法登录页面显示 403缺少 CSRF 令牌表单里加{% csrf_token %}登录成功但一直跳回登录页LOGIN_REDIRECT_URL未配置或 next 参数失效设置跳转地址检查视图是否被装饰器保护退出登录时报 Method Not Allowed用了 GET 请求登出改成 POST 表单提交未登录访问发布页报 404LOGIN_URL配置不对检查 settings 里LOGIN_URL与 urls 中 name 是否一致后台能登录但看不到文章管理用户不是is_staff分配后台权限或改用 admin 账号删除分类时系统报错外键设置了PROTECT查看哪些文章还在引用该分类先处理旧数据权限这块绝大多数实际问题不是“用户能看不该看的”而是“用户连该看的都看不了”。原因多半出在装饰器用错位置或者模板里变量名写错。我用这几个细节对照检查后基本能把 90% 的登录问题解决掉。5.3 对博客功能的进一步扩展建议博客系统做到这里已经能完成“创作、发布、管理、登录、删除、回收站”的完整闭环了。后续扩展方向有很多但我不建议一上来就全做。根据我自己的经验优先级应该是第一个是评论功能。评论涉及用户、文章、审核三层比博客本身更能锻炼业务设计能力。可以先做“登录用户才能评论、博主可删除评论”再考虑嵌套回复和邮件通知。第二个是 RSS 订阅。Django 内置的syndication框架可以快速输出 RSS 2.0 订阅源技术难度低但很实用。第三个是 REST API为以后小程序或手机 App 做数据接口。用django-rest-framework要注意接口的权限控制和序列化设计。第四个才是部署上线。用gunicorn加 Nginx 再配 HTTPS其实也是一套自己的知识点。把这个流程跑通你才真正从一个“写代码的人”变成一个“上线产品的人”。我个人在实际操作中最深的一点体会是博客系统这类全栈项目最大的价值不在于用了多新的技术而在于它让你把 Django 最核心的 ORM、认证、模板、路由、Admin 全部串起来了。每一次踩坑都是对框架运行机制更深一层的理解。你做完这一个项目再去学 DRF、Celery、Docker 这些周边工具会更加有的放矢因为你已经知道它们在为哪一环服务。我在跑这个博客系统的过程中逐渐养成了一种习惯每加一个新功能我都会先问自己一句“这个功能解决了谁的问题有没有更简单的替代方案”。比如我一度想给文章加浏览量排行榜后来发现首页列表按时间排序其实已经满足了绝大多数读者的需求就把更多精力放在了编辑器体验上。对新手来说少即是多先让一个完整的闭环稳定跑起来再谈优化和加花。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

用Frida-RPC实现安卓逆向:演唱会数据自动化获取实践 2026/10/2 4:31:23

用Frida-RPC实现安卓逆向:演唱会数据自动化获取实践

说实话,第一次把目标锁定在“安卓逆向 演唱会数据”这两个词上的时候,我脑子里蹦出来的第一个念头是:这东西能做成自动化吗?很多人一提逆向就想到破解、脱壳、分析so文件,一听就觉得门槛特别高。但真正把这些流程跑下…

阅读更多 →
Unity手游iOS Deep Link全链路实战:URL Scheme与Universal Links配置及参数传递 2026/10/2 4:31:17

Unity手游iOS Deep Link全链路实战:URL Scheme与Universal Links配置及参数传递

1. 为什么手游团队绕不开 Deep Link 这件事做过手游投放或者运营的兄弟应该都有体会:买量成本一年比一年高,用户点进来一次不容易,结果从浏览器点开广告、跳转到 App Store、下载、首次启动,这一整条链路上只要有一环断了&#xf…

阅读更多 →
AI+CAD落地实战:从Demo到工程化的技术难点与解决方案 2026/10/2 4:31:17

AI+CAD落地实战:从Demo到工程化的技术难点与解决方案

1. 为什么“AI CAD”的Demo看起来很美1.1 一个典型Demo的诞生过程先说说我见过最多的那类演示。打开一个网页,上传一张户型图或者机械零件的照片,点一下“生成CAD”,几秒钟后屏幕上出现一堆线条,看起来像模像样。再点一下“导出D…

阅读更多 →
速达财务SSTD3G服务器端部署全攻略:从解压到客户端连接 2026/10/2 4:30:57

速达财务SSTD3G服务器端部署全攻略:从解压到客户端连接

简介:速达财务SSTD3G_server_6.37.zip 是围绕速达财务SSTD3G系统推出的服务器端与客户端安装资源,适合中小企业财务部门及负责系统部署的IT人员使用。压缩包大小约316.81MB,已有404人学习。该安装资源覆盖服务器端与客户端两部分,…

阅读更多 →
PSO优化Kmeans聚类:居民用电行为分析实战 2026/10/2 4:30:57

PSO优化Kmeans聚类:居民用电行为分析实战

去年我接了个居民用电数据分析项目,核心目标很明确:根据智能电表采集的负荷曲线,把小区里几百户居民划分成几种典型的用电行为模式。我想着这不就是聚类嘛,直接Matlab里调个Kmeans函数分分钟搞定。结果第一版跑出来,轮…

阅读更多 →
Unity手游iOS Deep Link实战:URL Scheme与Universal Links配置及C#参数投递 2026/10/2 4:30:56

Unity手游iOS Deep Link实战:URL Scheme与Universal Links配置及C#参数投递

1. 为什么手游团队绕不开 Deep Link 这件事做过手游投放或者拉新活动的兄弟应该都有体会:买量买来的用户,点开广告之后如果只是被丢到 App Store 下载页,装完打开游戏却停在登录界面,那这个转化链路基本就废了一半。用户明明是被某…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉