当前位置:首页 > 技术 > 正文内容

基于Django的仿BBS项目开发实践

访客 技术 2026年9月8日 1

目录- 仿BBS项目开发

  • day63
  • 1.项目开发流程概述
  • 2.数据库模型设计
  • 3.用户注册模块实现
  • 1)表单验证类编写
  • 2)注册功能实现
  • 4.用户登录模块实现
  • 1)动态验证码生成
  • day64
  • 5.首页功能开发
  • 1)登录状态判断
  • 2)密码修改功能
  • 3)Admin后台配置
  • (1)超级用户创建
  • (2)模型注册配置
  • (3)数据管理优化
  • 4)文章列表展示
  • 5)头像上传功能
  • (1)Media配置
  • (2)资源访问控制
  • 6.个人站点开发
  • 1)防盗链机制解析
  • 2)站点页面构建
  • 3)模板继承应用
  • 4)侧边栏功能
  • (1)数据聚合展示
  • day65
      • (2)筛选功能实现
  • 5)文章详情页开发
  • (1)页面结构分析
  • (2)点赞/踩功能
  • (3)评论系统实现
  • ①根评论逻辑
  • day66
        • ②根评论优化
  • ③子评论逻辑
  • ④子评论优化
  • 7.Admin后台开发
  • 1)后台界面搭建
  • 2)文章发布页面
  • 3)文章管理功能
  • (1)富文本编辑器集成
  • (2)内容安全处理
  • (3)文章发布逻辑
  • (4)爬虫模块应用
  • day67
      • (3)图片上传适配
  • 4)文章编辑功能
  • 5)文章删除功能
  • 6)头像修改功能
  • 7)分类标签管理
  • 8)用户绑定优化
  • 8.项目总结
  • 9.邮件发送功能

仿BBS项目开发

day63

1.项目开发流程概述

1.需求分析 2.系统架构设计 3.模块划分开发 4.测试验收 5.上线部署

2.数据库模型设计

核心功能:文章CRUD操作

  • 1.确定数据表结构
1.用户表
2.个人站点表
3.文章表
4.分类表
5.标签表
6.互动记录表
7.评论表

  • 2.字段设计规范
-用户表
    扩展auth_user表(电话、头像、注册时间)
-个人站点表
    站点名称(jason/torry)
    站点标题
    样式配置
-文章表
    标题
    摘要
    内容
    发布时间
-分类表
    分类名称
-标签表
    标签名称
-互动记录表
    用户ID(外键)
    文章ID(外键)
    互动类型
-评论表
    用户ID(外键)
    文章ID(外键)
    内容
    时间
    父评论ID
  • 3.外键关系设计
-用户表
    与个人站点表为一对一关系

-文章表
    与站点表为一对多
    与分类表为一对多
    与标签表为多对多
    增加统计字段:
        评论数
        点赞数
        点踩数

3.用户注册模块

1)表单验证类编写

# forms_utils.py
class RegisterForm(forms.Form):
    username = forms.CharField(max_length=20)
    password = forms.CharField(widget=forms.PasswordInput)
    confirm_password = forms.CharField(widget=forms.PasswordInput)
    email = forms.EmailField()
    
    def clean_username(self):
        # 验证用户名唯一性
        pass
    
    def clean(self):
        # 验证两次密码一致
        pass

2)注册功能实现

1.表单渲染
2.头像上传处理
3.AJAX文件传输
4.数据校验
5.错误反馈

# views.py
def register(request):
    if request.method == 'POST':
        form = RegisterForm(request.POST, request.FILES)
        if form.is_valid():
            # 创建用户并保存头像
            pass

4.用户登录模块

1)动态验证码生成

from PIL import Image, ImageDraw, ImageFont
import random

def generate_captcha(request):
    # 创建图片对象
    img = Image.new('RGB', (200, 60), get_random_color())
    draw = ImageDraw.Draw(img)
    font = ImageFont.truetype('static/fonts/arial.ttf', 32)
    
    # 生成验证码
    code = ''.join(random.choices('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', k=4))
    request.session['captcha'] = code
    
    # 绘制干扰线和文字
    for _ in range(5):
        draw.line([random.randint(0, 200), random.randint(0, 60), 
                  random.randint(0, 200), random.randint(0, 60)], fill='white')
    
    # 返回图片数据
    img_byte = BytesIO()
    img.save(img_byte, 'PNG')
    return HttpResponse(img_byte.getvalue(), content_type='image/png')

前端交互:

![](/generate_captcha/)
<script>
$('#captcha').click(function() {
    $(this).attr('src', '/generate_captcha/?t=' + Math.random());
});
</script>

day64

5.首页功能开发

1)登录状态判断

{% if user.is_authenticated %}
  <li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
      {{ user.username }} <span class="caret"></span>
    </a>
    - [修改密码](<{% url 'change_password' %}>)
- [退出登录](<{% url 'logout' %}>)
  </li>
{% else %}
  <li><a href="{% url 'register' %}">注册</a></li>
  <li><a href="{% url 'login' %}">登录</a></li>
{% endif %}

2)密码修改功能

@login_required
def change_password(request):
    if request.method == 'POST':
        old_pwd = request.POST.get('old_password')
        new_pwd = request.POST.get('new_password')
        
        if request.user.check_password(old_pwd):
            if new_pwd:
                request.user.set_password(new_pwd)
                request.user.save()
                return JsonResponse({'status': 'success'})
        return JsonResponse({'status': 'error', 'message': '密码验证失败'})

3)Admin后台配置

(1)超级用户创建
python manage.py createsuperuser
# 用户名: admin
# 密码: 123456
(2)模型注册配置
# admin.py
from django.contrib import admin
from .models import User, Site, Article, Category, Tag, Comment

admin.site.register(User)
admin.site.register(Site)
admin.site.register(Article)
admin.site.register(Category)
admin.site.register(Tag)
admin.site.register(Comment)
(3)数据管理优化
class UserAdmin(admin.ModelAdmin):
    list_display = ('username', 'email', 'date_joined')
    search_fields = ('username',)

admin.site.register(User, UserAdmin)

4)文章列表展示

def home(request):
    articles = Article.objects.all()
    paginator = Paginator(articles, 10)
    page = paginator.get_page(request.GET.get('page'))
    return render(request, 'home.html', {'page': page})

5)头像上传功能

(1)Media配置
# settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
(2)资源访问控制
# urls.py
from django.conf import settings
from django.conf.urls.static import static

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

day65

(2)侧边栏筛选
re_path(r'^(?P<username>\w+)/(?P<filter_type>category|tag|archive)/(?P<value>.+)/', views.site_view)

def site_view(request, username, filter_type=None, value=None):
    site = get_object_or_404(Site, site_name=username)
    articles = Article.objects.filter(site=site)
    
    if filter_type == 'category':
        articles = articles.filter(category_id=value)
    elif filter_type == 'tag':
        articles = articles.filter(tags=value)
    elif filter_type == 'archive':
        year, month = value.split('-')
        articles = articles.filter(create_time__year=year, create_time__month=month)
    
    return render(request, 'site.html', {'articles': articles})

5)文章详情页开发

(1)页面结构分析
def article_detail(request, username, article_id):
    site = get_object_or_404(Site, site_name=username)
    article = get_object_or_404(Article, pk=article_id, site=site)
    comments = article.comment_set.all()
    return render(request, 'article_detail.html', {'article': article, 'comments': comments})
(2)点赞/踩功能
// 前端交互
$('#like-btn').click(function() {
    $.ajax({
        url: '/article/like/',
        method: 'POST',
        data: {
            article_id: {{ article.id }},
            is_like: true,
            csrfmiddlewaretoken: '{{ csrf_token }}'
        },
        success: function(response) {
            $('#like-count').text(response.like_count);
        }
    });
});
(3)评论系统实现
def add_comment(request):
    if request.method == 'POST':
        article_id = request.POST.get('article_id')
        content = request.POST.get('content')
        parent_id = request.POST.get('parent_id')
        
        article = get_object_or_404(Article, id=article_id)
        Comment.objects.create(
            user=request.user,
            article=article,
            content=content,
            parent_id=parent_id
        )
        return JsonResponse({'status': 'success'})

day66

②根评论优化
// 实时显示评论
$('#comment-form').submit(function(e) {
    e.preventDefault();
    let content = $('#comment-text').val();
    $('#comment-list').prepend(`<div class="comment">${content}</div>`);
    $('#comment-text').val('');
});
③子评论逻辑
def add_comment(request):
    if request.method == 'POST':
        article_id = request.POST.get('article_id')
        content = request.POST.get('content')
        parent_id = request.POST.get('parent_id')
        
        article = get_object_or_404(Article, id=article_id)
        Comment.objects.create(
            user=request.user,
            article=article,
            content=content,
            parent_id=parent_id
        )
        return JsonResponse({'status': 'success'})
④子评论优化
def get_comments(request, article_id):
    article = get_object_or_404(Article, id=article_id)
    comments = article.comment_set.select_related('user', 'parent').all()
    return render(request, 'comment_list.html', {'comments': comments})

day67

(3)富文本图片上传
def upload_image(request):
    if request.method == 'POST' and request.FILES.get('image'):
        image = request.FILES['image']
        # 保存图片到MEDIA_ROOT
        # 返回图片URL
        return JsonResponse({'url': '/media/' + image.name})

4)文章编辑功能

5)文章删除功能

6)头像修改功能

def change_avatar(request):
    if request.method == 'POST' and request.FILES.get('avatar'):
        user = request.user
        user.avatar = request.FILES['avatar']
        user.save()
        return redirect('profile')

7)分类标签管理

8)用户绑定优化

8.项目总结

技术要点:
- ORM模型设计
- 表单验证机制
- 文件上传处理
- 分页功能实现
- 评论系统开发
- 富文本编辑器集成
- XSS防护策略

难点突破:
1. 多表关联查询
2. 评论树状结构处理
3. 富文本内容过滤
4. 验证码安全机制
5. 后台管理配置

9.邮件发送功能

from django.core.mail import send_mail

def send_verification_email(request):
    send_mail(
        '验证码',
        '您的验证码是:123456',
        'noreply@example.com',
        [request.user.email],
        fail_silently=False,
    )

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。