每天40分玩转Django:实操博客应用

embedded/2024/12/21 7:30:52/

实操博客应用

一、内容概述

模块重要程度主要内容
项目初始化⭐⭐⭐⭐创建项目和应用
模型设计⭐⭐⭐⭐⭐文章、评论、用户模型
视图实现⭐⭐⭐⭐⭐增删改查功能
模板开发⭐⭐⭐⭐页面布局和样式
用户认证⭐⭐⭐⭐⭐用户登录和权限

二、项目结构

blog_project/
├── blog/
│   ├── __init__.py
│   ├── models.py
│   ├── views.py
│   ├── urls.py
│   ├── forms.py
│   └── templates/
│       └── blog/
│           ├── base.html
│           ├── post_list.html
│           ├── post_detail.html
│           └── post_form.html
├── static/
│   └── css/
│       └── style.css
└── manage.py

三、模型设计

python"># blog/models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from django.utils import timezoneclass Category(models.Model):name = models.CharField('分类名', max_length=100)created_at = models.DateTimeField('创建时间', auto_now_add=True)class Meta:verbose_name = '分类'verbose_name_plural = verbose_namedef __str__(self):return self.nameclass Post(models.Model):STATUS_CHOICES = [('draft', '草稿'),('published', '发布'),]title = models.CharField('标题', max_length=200)slug = models.SlugField('URL', max_length=200, unique_for_date='publish')author = models.ForeignKey(User,on_delete=models.CASCADE,related_name='blog_posts',verbose_name='作者')category = models.ForeignKey(Category,on_delete=models.SET_NULL,null=True,blank=True,related_name='posts',verbose_name='分类')content = models.TextField('内容')publish = models.DateTimeField('发布时间', default=timezone.now)created = models.DateTimeField('创建时间', auto_now_add=True)updated = models.DateTimeField('更新时间', auto_now=True)status = models.CharField('状态',max_length=10,choices=STATUS_CHOICES,default='draft')views = models.PositiveIntegerField('浏览量', default=0)class Meta:ordering = ('-publish',)verbose_name = '文章'verbose_name_plural = verbose_namedef __str__(self):return self.titledef get_absolute_url(self):return reverse('blog:post_detail', args=[self.publish.year,self.publish.strftime('%m'),self.publish.strftime('%d'),self.slug])class Comment(models.Model):post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name='comments',verbose_name='文章')author = models.ForeignKey(User,on_delete=models.CASCADE,related_name='comments',verbose_name='作者')content = models.TextField('评论内容')created = models.DateTimeField('创建时间', auto_now_add=True)active = models.BooleanField('是否可见', default=True)parent = models.ForeignKey('self',on_delete=models.CASCADE,null=True,blank=True,related_name='replies',verbose_name='父评论')class Meta:ordering = ('created',)verbose_name = '评论'verbose_name_plural = verbose_namedef __str__(self):return f'Comment by {self.author} on {self.post}'

四、表单设计

python"># blog/forms.py
from django import forms
from .models import Post, Commentclass PostForm(forms.ModelForm):class Meta:model = Postfields = ['title', 'slug', 'content', 'category', 'status']widgets = {'title': forms.TextInput(attrs={'class': 'form-control'}),'slug': forms.TextInput(attrs={'class': 'form-control'}),'content': forms.Textarea(attrs={'class': 'form-control'}),'category': forms.Select(attrs={'class': 'form-control'}),'status': forms.Select(attrs={'class': 'form-control'}),}class CommentForm(forms.ModelForm):class Meta:model = Commentfields = ['content']widgets = {'content': forms.Textarea(attrs={'class': 'form-control','rows': 4,'placeholder': '请输入评论内容'}),}

五、视图实现

python"># blog/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.contrib import messages
from .models import Post, Comment, Category
from .forms import PostForm, CommentFormdef post_list(request):post_list = Post.objects.filter(status='published')paginator = Paginator(post_list, 10)page_number = request.GET.get('page')posts = paginator.get_page(page_number)categories = Category.objects.all()return render(request, 'blog/post_list.html', {'posts': posts,'categories': categories,})def post_detail(request, year, month, day, slug):post = get_object_or_404(Post, status='published',slug=slug,publish__year=year,publish__month=int(month),publish__day=int(day))# 增加浏览量post.views += 1post.save()# 获取评论comments = post.comments.filter(active=True, parent=None)if request.method == 'POST':comment_form = CommentForm(request.POST)if comment_form.is_valid():new_comment = comment_form.save(commit=False)new_comment.post = postnew_comment.author = request.usernew_comment.save()messages.success(request, '评论发表成功!')return redirect('blog:post_detail', year=year, month=month, day=day, slug=slug)else:comment_form = CommentForm()return render(request, 'blog/post_detail.html', {'post': post,'comments': comments,'comment_form': comment_form,})@login_required
def post_create(request):if request.method == 'POST':form = PostForm(request.POST)if form.is_valid():post = form.save(commit=False)post.author = request.userpost.save()messages.success(request, '文章创建成功!')return redirect(post.get_absolute_url())else:form = PostForm()return render(request, 'blog/post_form.html', {'form': form})@login_required
def post_edit(request, post_id):post = get_object_or_404(Post, id=post_id, author=request.user)if request.method == 'POST':form = PostForm(request.POST, instance=post)if form.is_valid():post = form.save()messages.success(request, '文章更新成功!')return redirect(post.get_absolute_url())else:form = PostForm(instance=post)return render(request, 'blog/post_form.html', {'form': form})

六、URL配置

python"># blog/urls.py
from django.urls import path
from . import viewsapp_name = 'blog'urlpatterns = [path('', views.post_list, name='post_list'),path('<int:year>/<int:month>/<int:day>/<slug:slug>/',views.post_detail, name='post_detail'),path('create/', views.post_create, name='post_create'),path('edit/<int:post_id>/', views.post_edit, name='post_edit'),
]

七、模板设计

<!-- blog/templates/blog/base.html -->
<!DOCTYPE html>
<html lang="zh-hans">
<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.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body><nav class="navbar navbar-expand-lg navbar-dark bg-dark"><div class="container"><a class="navbar-brand" href="{% url 'blog:post_list' %}">博客</a><div class="collapse navbar-collapse"><ul class="navbar-nav ms-auto">{% if user.is_authenticated %}<li class="nav-item"><a class="nav-link" href="{% url 'blog:post_create' %}">写文章</a></li><li class="nav-item"><span class="nav-link">{{ user.username }}</span></li>{% else %}<li class="nav-item"><a class="nav-link" href="{% url 'login' %}">登录</a></li>{% endif %}</ul></div></div></nav><div class="container mt-4">{% if messages %}{% for message in messages %}<div class="alert alert-{{ message.tags }}">{{ message }}</div>{% endfor %}{% endif %}{% block content %}{% endblock %}</div><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

八、流程图

在这里插入图片描述

九、扩展功能建议

  1. 文章功能扩展

    • 文章标签系统
    • 文章搜索功能
    • 文章归档功能
    • 相关文章推荐
  2. 用户功能扩展

    • 用户个人中心
    • 用户关注系统
    • 消息通知系统
  3. 评论功能扩展

    • 评论点赞功能
    • 评论回复通知
    • 评论审核系统
  4. 界面优化

    • 响应式设计
    • 富文本编辑器
    • 图片上传功能

十、总结

以上完成了一个基础的博客系统,包括:

  1. 文章的CRUD操作
  2. 评论系统的实现
  3. 用户认证和权限控制
  4. 分类系统的建立

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!


http://www.ppmy.cn/embedded/147473.html

相关文章

NOTEBOOK_11 汽车电子设备分享(工作经验)

汽车电子设备分享 摘要 本文主要列出汽车电子应用的一些实验设备和生产设备&#xff0c;部分会给予一定推荐。目录 摘要一、通用工具&#xff1a;二、测量与测试仪器2.1测量仪器2.2无线通讯测量仪器2.3元器件测试仪2.4安规测试仪2.5电源供应器2.6电磁兼容测试设备2.7可靠性环境…

rust与python互通

互通三件套 rust侧与python互通的三个库&#xff1a; pyo3 pythonize serde pyo3 pyo3跟用Python C API写python扩展有点类似&#xff0c;核心是&#xff1a; #[pymodule] #[pyfunction]两个注解。前者对应Py_InitModule&#xff0c;后者对应PyMethodDef。 下面是其它博…

SYD881X RTC定时器事件在调用timeAppClockSet后会出现比较大的延迟

RTC定时器事件在调用timeAppClockSet后会出现比较大的延迟 这里RTC做了两个定时器一个是12秒,一个是185秒: #define RTCEVT_NUM ((uint8_t) 0x02)//当前定时器事件数#define RTCEVT_12S ((uint32_t) 0x0000002)//定时器1s事件 /*整分钟定时器事件&#xff0c;因为其余的…

PHP基础

PHP代码标记 标准标记&#xff1a;<?php ?> PHP注释 单行&#xff1a;// # 多行&#xff1a;/* */ 两种浏览器输出文本的方式&#xff1a;echo 和 print echo <?php header("Content-Type:text/html;charsetutf-8"); // 输出字符串 ec…

将OBJ或GLB文件转换为3DTiles

格式简介 GLB文件&#xff08;.GLB&#xff09;代表“GL传输格式二进制文件”&#xff0c;是用于共享3D数据的标准化文件格式。确切地说&#xff0c;它可以包含有关三维模型、场景、模型、光源、材质、节点层次和动画的信息。 OBJ文件是一种文本文件格式&#xff0c;这就意味…

防御 XSS 的七条原则

前言 本文将会着重介绍防御XSS攻击的一些原则&#xff0c;需要读者对于XSS有所了解&#xff0c;至少知道XSS漏洞的基本原理&#xff0c; 攻击者可以利用XSS漏洞向用户发送攻击脚本&#xff0c;而用户的浏览器因为没有办法知道这段脚本是不可信的&#xff0c;所以依然会执行它…

【人工智能数学基础】——深入详解贝叶斯理论:掌握贝叶斯定理及其在分类和预测中的应用

深入详解贝叶斯理论&#xff1a;掌握贝叶斯定理及其在分类和预测中的应用 贝叶斯理论&#xff08;Bayesian Theory&#xff09;是概率论和统计学中的一个重要分支&#xff0c;它以托马斯贝叶斯&#xff08;Thomas Bayes&#xff09;命名&#xff0c;主要关注如何根据新的证据更…

从 Promise 到 Axios:轻松解锁异步编程

如果你正在开发中处理异步任务&#xff0c;比如网络请求、文件操作&#xff0c;或者用户交互的处理&#xff0c;那么你一定接触过 Promise 和 Async/Await。它们是现代 JavaScript 异步编程的基石。本文将带你一步步深入了解&#xff0c;帮助你弄清它们的背景、解决的问题以及实…