14.2 核心功能开发(一):文章管理
Django6个人博客系统开发(一):文章管理核心功能
本教程详细讲解使用Django6构建个人博客系统的文章管理功能,涵盖模型定义与迁移、列表与详情页开发、发布编辑删除操作,以及分类和标签的关联管理,适合Django6新手学习。
Django6个人博客系统开发(一):文章管理核心功能
引言
欢迎来到Django6个人博客系统教程的第一部分!在这部分中,我们将专注于博客的核心功能:文章管理。如果你是Django新手,别担心,我会一步步带你从零开始,学习如何定义文章模型、进行数据库迁移、开发文章列表和详情页面,并实现文章的发布、编辑、删除功能,同时管理分类和标签。本教程假设你已经安装了Django6并创建了项目,但我会尽量详细解释每个步骤。
文章模型定义与迁移
定义模型
在Django中,模型是数据库的蓝图。我们首先需要定义文章相关的模型。假设项目名为blog,在blog/models.py文件中编写以下代码:
from django.db import models
from django.contrib.auth.models import User # 引入用户模型,用于关联文章作者
# 分类模型
class Category(models.Model):
name = models.CharField(max_length=100, unique=True, verbose_name='分类名称')
description = models.TextField(blank=True, verbose_name='分类描述')
def __str__(self):
return self.name # 方便在管理后台显示
# 标签模型
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True, verbose_name='标签名称')
def __str__(self):
return self.name
# 文章模型
class Article(models.Model):
title = models.CharField(max_length=200, verbose_name='文章标题')
content = models.TextField(verbose_name='文章内容')
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='作者') # 外键关联用户,删除用户时文章也删除
published_date = models.DateTimeField(auto_now_add=True, verbose_name='发布时间') # 自动设置发布时间
updated_date = models.DateTimeField(auto_now=True, verbose_name='更新时间') # 每次保存时自动更新
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='分类') # 可选分类,允许为空
tags = models.ManyToManyField(Tag, blank=True, verbose_name='标签') # 多对多关系,文章可以有多个标签
def __str__(self):
return self.title # 方便在管理后台显示文章标题
解释:
- 我们定义了三个模型:
Category、Tag和Article。Article使用ForeignKey与Category关联,表示每篇文章属于一个分类(可选);使用ManyToManyField与Tag关联,表示文章可以有多个标签。 - 添加了
verbose_name参数,以便在管理后台显示中文名称,提升用户体验。 auto_now_add和auto_now是Django的便捷字段,自动处理日期时间。
迁移数据库
定义好模型后,需要将这些模型同步到数据库中。Django通过迁移系统管理数据库变化。运行以下命令:
# 生成迁移文件
python manage.py makemigrations blog # 如果你在blog应用下,可以不加blog
# 应用迁移
python manage.py migrate
解释:makemigrations命令会创建一个迁移文件,记录模型变化;migrate命令则实际应用这些变化,创建数据库表。
文章列表与详情页开发
创建视图
视图是处理用户请求并返回响应的函数。在blog/views.py中编写:
from django.shortcuts import render, get_object_or_404
from .models import Article
def article_list(request):
"""文章列表视图,显示所有文章"""
articles = Article.objects.all().order_by('-published_date') # 查询所有文章,按发布时间降序排列
context = {
'articles': articles
}
return render(request, 'blog/article_list.html', context)
def article_detail(request, article_id):
"""文章详情视图,根据ID显示单篇文章"""
article = get_object_or_404(Article, id=article_id) # 如果文章不存在,返回404错误页面
context = {
'article': article
}
return render(request, 'blog/article_detail.html', context)
解释:order_by('-published_date')确保最新文章在前;get_object_or_404是一个便捷函数,简化了错误处理。
URL路由
接下来,在blog/urls.py中配置URL路径(如果还没有这个文件,请在blog应用下创建)。
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list, name='article_list'), # 文章列表页
path('articles/<int:article_id>/', views.article_detail, name='article_detail'), # 文章详情页
]
同时,确保项目的主urls.py中包含了这个应用的URL配置。例如,在myproject/urls.py中添加:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')), # 包含blog应用的URL
]
模板开发
模板是用于渲染HTML页面的文件。首先,创建模板目录blog/templates/blog/,然后创建两个模板文件:
article_list.html:显示文章列表。
<!-- 假设基础模板在templates/base.html中,使用继承简化代码 -->
{% extends 'base.html' %}
{% block content %}
<h1>文章列表</h1>
<ul>
{% for article in articles %}
<li>
<a href="{% url 'article_detail' article.id %}">{{ article.title }}</a>
<small> - 发布时间:{{ article.published_date|date:'Y-m-d H:i' }}</small>
</li>
{% empty %}
<li>暂无文章。</li>
{% endfor %}
</ul>
{% endblock %}
article_detail.html:显示单篇文章详情。
{% extends 'base.html' %}
{% block content %}
<h1>{{ article.title }}</h1>
<p><strong>作者:</strong>{{ article.author.username }}</p>
<p><strong>发布时间:</strong>{{ article.published_date|date:'Y-m-d H:i' }} | <strong>更新时间:</strong>{{ article.updated_date|date:'Y-m-d H:i' }}</p>
<div>{{ article.content }}</div>
<p><strong>分类:</strong>{% if article.category %}{{ article.category.name }}{% else %}未分类{% endif %}</p>
<p><strong>标签:</strong>
{% for tag in article.tags.all %}
{{ tag.name }}{% if not forloop.last %}, {% endif %}
{% empty %}
无标签
{% endfor %}
</p>
<a href="{% url 'article_list' %}">返回文章列表</a>
{% endblock %}
解释:使用Django模板标签{% url %}生成动态URL;|date是模板过滤器,格式化日期显示。
文章发布、编辑、删除功能实现
表单创建
Django提供了ModelForm来简化表单创建。在blog/forms.py中创建:
from django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'content', 'category', 'tags'] # 排除author等自动填充的字段
解释:ModelForm自动根据模型生成表单字段,省去手动定义字段的麻烦。
视图实现
在blog/views.py中添加创建、编辑和删除视图:
from django.shortcuts import render, redirect, get_object_or_404
from .models import Article
from .forms import ArticleForm
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() # 保存文章
form.save_m2m() # 保存多对多关系(如标签)
return redirect('article_detail', article_id=article.id) # 重定向到详情页
else:
form = ArticleForm()
context = {'form': form}
return render(request, 'blog/article_form.html', context)
def article_edit(request, article_id):
"""编辑已有文章"""
article = get_object_or_404(Article, id=article_id)
if request.method == 'POST':
form = ArticleForm(request.POST, instance=article) # instance参数指定要编辑的实例
if form.is_valid():
form.save()
return redirect('article_detail', article_id=article.id)
else:
form = ArticleForm(instance=article)
context = {'form': form}
return render(request, 'blog/article_form.html', context)
def article_delete(request, article_id):
"""删除文章"""
article = get_object_or_404(Article, id=article_id)
if request.method == 'POST':
article.delete()
return redirect('article_list') # 删除后返回列表页
context = {'article': article}
return render(request, 'blog/article_confirm_delete.html', context)
解释:
commit=False允许我们在保存前添加额外数据(如作者)。save_m2m()是必须的,用于保存多对多字段。- 删除操作使用POST方法以确保安全(防止CSRF攻击)。
更新URL和模板
在blog/urls.py中添加新URL:
urlpatterns = [
path('articles/', views.article_list, name='article_list'),
path('articles/<int:article_id>/', views.article_detail, name='article_detail'),
path('articles/new/', views.article_create, name='article_create'), # 发布文章
path('articles/<int:article_id>/edit/', views.article_edit, name='article_edit'), # 编辑文章
path('articles/<int:article_id>/delete/', views.article_delete, name='article_delete'), # 删除文章
]
创建表单模板article_form.html:
{% extends 'base.html' %}
{% block content %}
<h1>{% if form.instance.pk %}编辑文章{% else %}发布新文章{% endif %}</h1>
<form method="post">
{% csrf_token %} <!-- 必须的CSRF令牌,用于安全 -->
{{ form.as_p }} <!-- 以段落形式渲染表单字段 -->
<button type="submit">保存</button>
<a href="{% url 'article_list' %}">取消</a>
</form>
{% endblock %}
创建删除确认模板article_confirm_delete.html:
{% extends 'base.html' %}
{% block content %}
<h1>确认删除</h1>
<p>您确定要删除文章 "{{ article.title }}" 吗?</p>
<form method="post">
{% csrf_token %}
<button type="submit">确认删除</button>
<a href="{% url 'article_detail' article.id %}">取消</a>
</form>
{% endblock %}
解释:{% csrf_token %}是Django的安全机制,防止跨站请求伪造攻击。
分类与标签关联管理
我们已经在上面的模型中定义了分类和标签的关联。为了管理它们,可以创建一个简单的视图或使用Django的管理后台。这里,我们使用Django内置的管理后台进行管理,这对新手更友好。
首先,在blog/admin.py中注册模型:
from django.contrib import admin
from .models import Category, Tag, Article
admin.site.register(Category)
admin.site.register(Tag)
admin.site.register(Article)
然后,运行服务器(python manage.py runserver),访问/admin/,使用超级用户登录(可以通过python manage.py createsuperuser创建)。在管理后台,你可以轻松添加、编辑分类和标签,并在文章表单中关联它们。
解释:Django管理后台是一个强大的工具,可以快速管理数据,无需编写额外代码。在文章表单中,会自动显示下拉菜单(分类)和多选框(标签)。
结语
恭喜!你已经完成了Django6个人博客系统文章管理核心功能的开发。我们学会了定义模型、进行迁移、开发视图和模板,并实现了文章的CRUD(创建、读取、更新、删除)操作,同时集成了分类和标签管理。这为后续添加更多功能(如用户认证、搜索、评论等)打下了基础。
在下一部分,我们将扩展功能,例如添加用户权限控制、优化UI等。希望本教程对你有所帮助,如果有问题,随时查阅Django官方文档或社区资源。祝你在Django学习之路上顺利前行!