基于 Vue + Django + MySQL 实现个人博客/CMS系统

目录

[1. 环境搭建与项目初始化](#1. 环境搭建与项目初始化)

后端 (Django)

[2. 数据库模型设计](#2. 数据库模型设计)

用户认证模型 (Django Auth)

文章模型 (models.py)

全文索引优化

[3. 后端API开发 (Django REST Framework)](#3. 后端API开发 (Django REST Framework))

用户注册/登录

文章发布与搜索

[4. 前端实现 (Vue 3)](#4. 前端实现 (Vue 3))

项目初始化

核心功能实现

[5. 访问统计实现](#5. 访问统计实现)

后端中间件记录PV/UV

[6. 部署与优化](#6. 部署与优化)

关键问题解决


1. 环境搭建与项目初始化

后端 (Django)

  1. 创建Django项目

    bash 复制代码
    django-admin startproject blog_backend
    cd blog_backend
    python manage.py startapp blog
  2. 安装依赖

    bash 复制代码
    pip install django djangorestframework django-cors-headers djangorestframework-simplejwt mysqlclient
  3. 配置MySQL数据库

    修改 settings.py

    python 复制代码
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'blog_db',
            'USER': 'root',
            'PASSWORD': 'your_password',
            'HOST': 'localhost',
            'PORT': '3306',
        }
    }
  4. 配置DRF和JWT

    修改 settings.py

python 复制代码
INSTALLED_APPS = [
    # ...
    'rest_framework',
    'corsheaders',
    'blog',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    # ...
]

CORS_ALLOW_ALL_ORIGINS = True  # 开发阶段允许所有跨域

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
}

2. 数据库模型设计

用户认证模型 (Django Auth)

直接使用Django内置的 User 模型,无需额外设计。

文章模型 (models.py)

python 复制代码
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()  # 存储Markdown或HTML内容
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    category = models.CharField(max_length=50)
    tags = models.CharField(max_length=100)  # 逗号分隔的标签,如 "Python,Web"
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

class Comment(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField()
    parent_comment = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True)  # 树形评论
    created_at = models.DateTimeField(auto_now_add=True)

全文索引优化

在MySQL中为 Article 表添加全文索引:

sql 复制代码
ALTER TABLE blog_article ADD FULLTEXT(title, content);

3. 后端API开发 (Django REST Framework)

用户注册/登录

  1. 序列化器 (serializers.py)

    python 复制代码
    from rest_framework import serializers
    from django.contrib.auth.models import User
    
    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ('id', 'username', 'email', 'password')
            extra_kwargs = {'password': {'write_only': True}}
    
        def create(self, validated_data):
            user = User.objects.create_user(**validated_data)
            return user
  2. 视图 (views.py)

    python 复制代码
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework_simplejwt.tokens import RefreshToken
    
    class RegisterView(APIView):
        def post(self, request):
            serializer = UserSerializer(data=request.data)
            if serializer.is_valid():
                user = serializer.save()
                refresh = RefreshToken.for_user(user)
                return Response({
                    'refresh': str(refresh),
                    'access': str(refresh.access_token),
                })
            return Response(serializer.errors, status=400)

文章发布与搜索

  1. 文章序列化器

    python 复制代码
    class ArticleSerializer(serializers.ModelSerializer):
        class Meta:
            model = Article
            fields = '__all__'
  2. 文章搜索接口

    使用Django ORM的全文搜索:

    python 复制代码
    class ArticleSearchView(APIView):
        def get(self, request):
            query = request.query_params.get('q', '')
            # MySQL全文搜索语法
            articles = Article.objects.raw(
                "SELECT * FROM blog_article WHERE MATCH(title, content) AGAINST (%s)",
                [query]
            )
            serializer = ArticleSerializer(articles, many=True)
            return Response(serializer.data)

4. 前端实现 (Vue 3)

项目初始化

bash 复制代码
npm create vue@latest blog_frontend
cd blog_frontend
npm install axios vue-router vuex quill @vueuse/core

核心功能实现

  1. Markdown渲染

    使用 markedvue-markdown 库:

    html 复制代码
    <template>
      <div v-html="compiledMarkdown"></div>
    </template>
    
    <script setup>
    import { marked } from 'marked'
    const compiledMarkdown = marked(props.content)
    </script>
  2. 富文本编辑器集成 (Quill)

    html 复制代码
    <template>
      <div ref="editor"></div>
    </template>
    
    <script setup>
    import Quill from 'quill'
    import 'quill/dist/quill.snow.css'
    
    const editor = ref(null)
    onMounted(() => {
      const quill = new Quill(editor.value, {
        theme: 'snow',
        modules: { toolbar: true }
      })
    })
    </script>
  3. 动态路由SEO优化

    使用 vue-router 和预渲染插件 prerender-spa-plugin

    javascript 复制代码
    // vue.config.js
    const PrerenderSPAPlugin = require('prerender-spa-plugin')
    
    module.exports = {
      configureWebpack: {
        plugins: [
          new PrerenderSPAPlugin({
            staticDir: path.join(__dirname, 'dist'),
            routes: ['/', '/articles', '/about'],  // 预渲染的路由
          })
        ]
      }
    }

5. 访问统计实现

后端中间件记录PV/UV

  1. 创建访问记录模型

    python 复制代码
    class AccessLog(models.Model):
        ip = models.CharField(max_length=50)
        path = models.CharField(max_length=200)
        user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
        created_at = models.DateTimeField(auto_now_add=True)
  2. 中间件统计访问量

    python 复制代码
    class AccessLogMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            response = self.get_response(request)
            AccessLog.objects.create(
                ip=request.META.get('REMOTE_ADDR'),
                path=request.path,
                user=request.user if request.user.is_authenticated else None
            )
            return response

6. 部署与优化

  1. MySQL全文索引查询优化

    确保MySQL版本 >= 5.6,并配置索引:

    sql 复制代码
    CREATE FULLTEXT INDEX ft_idx ON blog_article(title, content);
  2. Nginx配置反向代理

    sql 复制代码
    server {
        listen 80;
        server_name your_domain.com;
    
        location /api {
            proxy_pass http://localhost:8000;
            proxy_set_header Host $host;
        }
    
        location / {
            root /path/to/vue/dist;
            try_files $uri $uri/ /index.html;
        }
    }
  3. 性能优化

    • 使用 django-debug-toolbar 分析查询

    • Vue路由懒加载:

      javascript 复制代码
      const routes = [
        { path: '/article/:id', component: () => import('./views/ArticleDetail.vue') }
      ]

关键问题解决

  1. 跨域配置

    使用 django-cors-headers,确保前端能访问后端API。

  2. 树形评论渲染

    前端递归组件实现:

    html 复制代码
    <template>
      <div v-for="comment in comments" :key="comment.id">
        <div>{{ comment.content }}</div>
        <CommentTree v-if="comment.replies" :comments="comment.replies"/>
      </div>
    </template>
  3. JWT Token自动刷新

    使用Axios拦截器:

    javascript 复制代码
    axios.interceptors.response.use(response => response, error => {
      if (error.response.status === 401) {
        return refreshToken().then(() => {
          return axios(error.config)
        })
      }
      return Promise.reject(error)
    })

通过以上步骤,你可以逐步搭建一个功能完整的博客系统。建议先从基础功能(如文章发布)开始,逐步迭代添加评论、搜索等模块。

相关推荐
黄毛火烧雪下2 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox13 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞16 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行16 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581017 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周20 分钟前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
王强你强26 分钟前
MySQL 高级查询:JOIN、子查询、窗口函数
数据库·mysql
草巾冒小子27 分钟前
brew 安装mysql,启动,停止,重启
数据库·mysql
三翼鸟数字化技术团队38 分钟前
Vue自定义指令最佳实践教程
前端·vue.js
The Future is mine41 分钟前
Python计算经纬度两点之间距离
开发语言·python