博客系统打造整体与设计
·
1 整体快速规划设计
1.1 系统软件体系架构

1.2 系统功能设计
文章管理:查看列表、文章详情、发表文章
用户认证:注册新用户、用户登录、用户注销
密码管理:修改密码(含完整性验证)
2 环境与体系架构
2.1 创建项目和应用
D:\myblogDsn>django-admin startproject myblogDsn
D:\myblogDsn>cd myblogDsn
D:\myblogDsn>python manage.py startapp blog
D:\myblogDsn>python manage.py startapp users
2.2 配置项目结构
设计myblog/settings.py,
import os
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
ROOT_URLCONF = 'myblogDsn.urls'
WSGI_APPLICATION = 'myblogDsn.wsgi.application'
# 安全配置(保留你自己的 SECRET_KEY)
SECRET_KEY = 'django-insecure-你原来的密钥'
DEBUG = True
ALLOWED_HOSTS = []
# 应用列表(你的应用已经配置好了)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # 博客应用
'users', # 用户应用
]
# 【核心】中间件配置(解决之前的 SystemCheckError)
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# 【核心】模板配置(解决 admin.E003 错误,匹配你的 templates 目录)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 告诉 Django 全局模板目录的位置
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# 数据库配置(默认 SQLite,不用改)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# 中文和时区配置
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
# 【核心】静态文件配置(匹配你的 static 目录,解决警告)
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / "static",
]
# 登录相关配置(你之前的配置,保留即可)
LOGIN_URL = '/users/login/'
LOGIN_REDIRECT_URL = '/blog/'
# Django 3.2+ 必须的配置
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
3 系统集编码设计
3.1 定义模型
设计blog/models.py
from django.db import models
from django.contrib.auth.models import User
class Article(models.Model):
"""文章模型"""
title = models.CharField('标题', max_length=200)
content = models.TextField('内容')
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='作者')
created_at = models.DateTimeField('创建时间', auto_now_add=True)
updated_at = models.DateTimeField('更新时间', auto_now=True)
class Meta:
verbose_name = '文章'
verbose_name_plural = '文章'
ordering = ['-created_at']
def __str__(self):
return self.title
# Create your models here.
3.2 创建管理后台
blog/admin.py
from django.contrib import admin
from .models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'created_at')
list_filter = ('created_at', 'author')
search_fields = ('title', 'content')
# Register your models here.
3.3 创建视图
blog/view.py
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from .models import Article
from .forms import ArticleForm
def article_list(request):
"""文章列表页"""
articles = Article.objects.all()
return render(request, 'blog/article_list.html', {'articles': articles})
def article_detail(request, pk):
"""文章详情页"""
article = get_object_or_404(Article, pk=pk)
return render(request, 'blog/article_detail.html', {'article': article})
@login_required
def article_create(request):
"""发表文章(需登录)"""
if request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
article = form.save(commit=False)
article.author = request.user
article.save()
return redirect('article_detail', pk=article.pk)
else:
form = ArticleForm()
return render(request, 'blog/article_form.html', {'form': form, 'action': '发表'})
# Create your views here.
3.4 基本窗口构造
blog/forms.py
from django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'content']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入文章标题'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 10, 'placeholder': '请输入文章内容'}),
}
labels = {
'title': '标题',
'content': '内容',
}
3.5 配置URL路由
blog/urls.py
from django.urls import path
from blog import views # 关键:从 blog 应用导入 views
urlpatterns = [
path('', views.article_list, name='article_list'),
path('article/<int:pk>/', views.article_detail, name='article_detail'),
path('create/', views.article_create, name='article_create'),
]
4 页面及其服务设计
4.1 创建表单
users/ forms.py
用户注册表单,包含完整的验证逻辑:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
class LoginForm(forms.Form):
"""登录表单"""
username = forms.CharField(
label='用户名',
max_length=100,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入用户名'})
)
password = forms.CharField(
label='密码',
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入密码'})
)
class RegisterForm(forms.Form):
"""注册表单,包含完整的验证逻辑"""
username = forms.CharField(
label='用户名',
max_length=20,
min_length=3,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '3-20个字符'}),
error_messages={
'required': '用户名不能为空',
'min_length': '用户名至少3个字符',
'max_length': '用户名最多20个字符'
}
)
email = forms.EmailField(
label='邮箱',
max_length=50,
widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': '请输入邮箱'}),
error_messages={'required': '邮箱不能为空', 'invalid': '请输入有效的邮箱地址'}
)
password = forms.CharField(
label='密码',
min_length=6,
max_length=18,
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '6-18个字符'}),
error_messages={
'required': '密码不能为空',
'min_length': '密码至少6个字符',
'max_length': '密码最多18个字符'
}
)
confirm_password = forms.CharField(
label='确认密码',
min_length=6,
max_length=18,
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '再次输入密码'}),
error_messages={
'required': '确认密码不能为空',
'min_length': '确认密码至少6个字符',
'max_length': '确认密码最多18个字符'
}
)
def clean_username(self):
"""验证用户名唯一性"""
username = self.cleaned_data['username']
if User.objects.filter(username=username).exists():
raise forms.ValidationError('该用户名已被注册')
return username
def clean_email(self):
"""验证邮箱唯一性"""
email = self.cleaned_data['email']
if User.objects.filter(email=email).exists():
raise forms.ValidationError('该邮箱已被注册')
return email
def clean(self):
"""验证两次密码一致性"""
cleaned_data = super().clean()
password = cleaned_data.get('password')
confirm_password = cleaned_data.get('confirm_password')
if password and confirm_password and password != confirm_password:
self.add_error('confirm_password', '两次密码输入不一致')
return cleaned_data
class ChangePasswordForm(forms.Form):
"""修改密码表单"""
old_password = forms.CharField(
label='原密码',
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入原密码'}),
error_messages={'required': '原密码不能为空'}
)
new_password = forms.CharField(
label='新密码',
min_length=6,
max_length=18,
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '6-18个字符'}),
error_messages={
'required': '新密码不能为空',
'min_length': '新密码至少6个字符',
'max_length': '新密码最多18个字符'
}
)
confirm_new_password = forms.CharField(
label='确认新密码',
min_length=6,
max_length=18,
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '再次输入新密码'}),
error_messages={
'required': '确认新密码不能为空',
'min_length': '确认新密码至少6个字符',
'max_length': '确认新密码最多18个字符'
}
)
def __init__(self, user, *args, **kwargs):
"""重写__init__,传入当前用户对象"""
self.user = user
super().__init__(*args, **kwargs)
def clean_old_password(self):
"""验证原密码是否正确"""
old_password = self.cleaned_data['old_password']
if not self.user.check_password(old_password):
raise forms.ValidationError('原密码不正确')
return old_password
def clean_new_password(self):
"""验证新密码是否与原密码相同"""
new_password = self.cleaned_data['new_password']
old_password = self.cleaned_data.get('old_password', '')
if new_password == old_password:
raise forms.ValidationError('新密码不能与原密码相同')
return new_password
def clean(self):
"""验证两次新密码一致性"""
cleaned_data = super().clean()
new_password = cleaned_data.get('new_password')
confirm_new_password = cleaned_data.get('confirm_new_password')
if new_password and confirm_new_password and new_password != confirm_new_password:
self.add_error('confirm_new_password', '两次密码输入不一致')
return cleaned_data
4.2 创建视图
(user/views.py)
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .forms import LoginForm, RegisterForm, ChangePasswordForm
def user_login(request):
"""用户登录"""
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, f'欢迎回来,{username}!')
# 获取next参数,实现登录后跳转到原页面
next_url = request.GET.get('next', '/blog/')
return redirect(next_url)
else:
messages.error(request, '用户名或密码错误')
else:
form = LoginForm()
return render(request, 'users/login.html', {'form': form})
def user_register(request):
"""用户注册"""
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
# 创建用户
user = User.objects.create_user(
username=username,
email=email,
password=password
)
# 注册后自动登录
login(request, user)
messages.success(request, f'注册成功,欢迎 {username}!')
return redirect('/blog/')
else:
form = RegisterForm()
return render(request, 'users/register.html', {'form': form})
def user_logout(request):
"""用户注销"""
logout(request)
messages.success(request, '您已成功退出登录')
return redirect('/blog/')
@login_required
def change_password(request):
"""修改密码"""
if request.method == 'POST':
form = ChangePasswordForm(request.user, request.POST)
if form.is_valid():
new_password = form.cleaned_data['new_password']
# 更新密码
request.user.set_password(new_password)
request.user.save()
# 更新密码后重新登录
login(request, request.user)
messages.success(request, '密码修改成功!')
return redirect('/blog/')
else:
form = ChangePasswordForm(request.user)
return render(request, 'users/change_password.html', {'form': form})
# Create your views here.
4.3 配置URL路由
(users/urls.py)
from django.urls import path
from . import views
urlpatterns = [
path('login/', views.user_login, name='login'),
path('register/', views.user_register, name='register'),
path('logout/', views.user_logout, name='logout'),
path('change_password/', views.change_password, name='change_password'),
]
(myblogDsn/urls.py)
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')),
path('users/', include('users.urls')),
# 根路径重定向到博客
path('', include('blog.urls')),
]
5 基础模板
5.1 博客首页模板设计
(templates/base.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}我的博客{% endblock %}</title>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
padding-top: 60px;
background-color: #f8f9fa;
}
.navbar-brand {
font-weight: bold;
}
.container {
max-width: 960px;
}
.messages {
margin-top: 20px;
}
</style>
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="{% url 'article_list' %}">📝 我的博客</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="{% url 'article_list' %}">首页</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'article_create' %}">发表文章</a>
</li>
</ul>
<ul class="navbar-nav">
{% if user.is_authenticated %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown">
👤 {{ user.username }}
</a>
<div class="dropdown-menu dropdown-menu-right">
<a class="dropdown-item" href="{% url 'change_password' %}">修改密码</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="{% url 'logout' %}">退出登录</a>
</div>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">登录</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'register' %}">注册</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<!-- 消息提示 -->
<div class="container messages">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert">×</button>
</div>
{% endfor %}
{% endif %}
</div>
<!-- 主内容 -->
<div class="container">
{% block content %}
{% endblock %}
</div>
<!-- 页脚 -->
<footer class="container text-center text-muted mt-5 mb-3">
<p>© 2026 我的博客 - Django学习项目</p>
</footer>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.bundle.min.js"></script>
</body>
</html>
5.2 博文操作模板设计
(blog/templates/blog/article_list.html)
{% extends 'base.html' %}
{% block title %}文章列表{% endblock %}
{% block content %}
<div class="row">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>📚 文章列表</h2>
<a href="{% url 'article_create' %}" class="btn btn-primary">✏️ 发表文章</a>
</div>
{% if articles %}
<div class="list-group">
{% for article in articles %}
<a href="{% url 'article_detail' article.pk %}" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{ article.title }}</h5>
<small class="text-muted">{{ article.created_at|date:"Y-m-d H:i" }}</small>
</div>
<p class="mb-1 text-muted">{{ article.content|truncatechars:100 }}</p>
<small>作者:{{ article.author.username }}</small>
</a>
{% endfor %}
</div>
{% else %}
<div class="alert alert-info">
还没有文章,<a href="{% url 'article_create' %}">赶快发表第一篇吧</a>!
</div>
{% endif %}
</div>
</div>
{% endblock %}
5.3 文章详情模板设计
(blog/templates/blog.article_detail.html)
{% extends 'base.html' %}
{% block title %}{{ article.title }}{% endblock %}
{% block content %}
<article class="card">
<div class="card-body">
<h1 class="card-title">{{ article.title }}</h1>
<div class="text-muted mb-3">
<span>作者:{{ article.author.username }}</span>
<span class="ml-3">发布时间:{{ article.created_at|date:"Y-m-d H:i:s" }}</span>
{% if article.updated_at != article.created_at %}
<span class="ml-3">最后更新:{{ article.updated_at|date:"Y-m-d H:i:s" }}</span>
{% endif %}
</div>
<hr>
<div class="card-text" style="line-height: 1.8;">
{{ article.content|linebreaks }}
</div>
<hr>
<a href="{% url 'article_list' %}" class="btn btn-secondary">← 返回列表</a>
</div>
</article>
{% endblock %}
5.4 发表文章模板设计
(blog/templates/blog/article_form.html)
{% extends 'base.html' %}
{% block title %}{{ action }}文章{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h3>{{ action }}文章</h3>
</div>
<div class="card-body">
<form method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{{ field }}
{% if field.errors %}
<small class="text-danger">{{ field.errors|join:", " }}</small>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary btn-block">
✅ 提交
</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
5.5 用户认证模板设计
(users/templates/users/login.html)
{% extends 'base.html' %}
{% block title %}用户登录{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3>🔑 用户登录</h3>
</div>
<div class="card-body">
<form method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{{ field }}
{% if field.errors %}
<small class="text-danger">{{ field.errors|join:", " }}</small>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary btn-block">登录</button>
</form>
<div class="text-center mt-3">
<p>还没有账号?<a href="{% url 'register' %}">立即注册</a></p>
<p><a href="{% url 'article_list' %}">回到首页</a></p>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
(users/templates/users/register.html)
{% extends 'base.html' %}
{% block title %}用户注册{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3>📝 用户注册</h3>
</div>
<div class="card-body">
<form method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{{ field }}
{% if field.errors %}
<small class="text-danger">{{ field.errors|join:", " }}</small>
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-success btn-block">注册</button>
</form>
<div class="text-center mt-3">
<p>已有账号?<a href="{% url 'login' %}">立即登录</a></p>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
5.6 修改密码模板设计
(users/templates/users/change_password.html)
{% extends 'base.html' %}
{% block title %}修改密码{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3>🔒 修改密码</h3>
</div>
<div class="card-body">
<form method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{{ field }}
{% if field.errors %}
<small class="text-danger">{{ field.errors|join:", " }}</small>
{% endif %}
</div>
{% endfor %}
<div class="alert alert-info">
<strong>密码要求:</strong>
<ul class="mb-0">
<li>长度在6-18个字符之间</li>
<li>新密码不能与原密码相同</li>
</ul>
</div>
<button type="submit" class="btn btn-warning btn-block">修改密码</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
6 创建超级管理员
用户名:admins
电子邮件地址:24365808398@qq.com
密码:11111111
7运行以及测试
7.1 运行
python manage.py runserver
博文网址:http://127.0.0.1:8000/
后台管理:http://127.0.0.1:8000/admin/
7.2 操控页面展现




7.3 数据库管护

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)