当前位置: 首页 > news >正文

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

目录

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

后端 (Django)

2. 数据库模型设计

用户认证模型 (Django Auth)

文章模型 (models.py)

全文索引优化

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

用户注册/登录

文章发布与搜索

4. 前端实现 (Vue 3)

项目初始化

核心功能实现

5. 访问统计实现

后端中间件记录PV/UV

6. 部署与优化

关键问题解决


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

后端 (Django)

  1. 创建Django项目

    django-admin startproject blog_backend
    cd blog_backend
    python manage.py startapp blog
  2. 安装依赖

    pip install django djangorestframework django-cors-headers djangorestframework-simplejwt mysqlclient
  3. 配置MySQL数据库
    修改 settings.py

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'blog_db',
            'USER': 'root',
            'PASSWORD': 'your_password',
            'HOST': 'localhost',
            'PORT': '3306',
        }
    }
  4. 配置DRF和JWT
    修改 settings.py

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)

    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 表添加全文索引:

    ALTER TABLE blog_article ADD FULLTEXT(title, content);

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

    用户注册/登录

    1. 序列化器 (serializers.py)

      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)

      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. 文章序列化器

      class ArticleSerializer(serializers.ModelSerializer):
          class Meta:
              model = Article
              fields = '__all__'
    2. 文章搜索接口
      使用Django ORM的全文搜索:

      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)

    项目初始化

    npm create vue@latest blog_frontend
    cd blog_frontend
    npm install axios vue-router vuex quill @vueuse/core

    核心功能实现

    1. Markdown渲染
      使用 marked 或 vue-markdown 库:

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

      <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

      // 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. 创建访问记录模型

      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. 中间件统计访问量

      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,并配置索引:

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

      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路由懒加载:

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

    关键问题解决

    1. 跨域配置
      使用 django-cors-headers,确保前端能访问后端API。

    2. 树形评论渲染
      前端递归组件实现:

      <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拦截器:

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

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

    相关文章:

  1. 基于单片机的音乐播放器系统设计
  2. FPGA学习-基于 DE2-115 板的 Verilog 分秒计数器设计与按键功能实现
  3. 第一章 EDA技术概述
  4. NLP高频面试题(三十)——LLama系列模型介绍,包括LLama LLama2和LLama3
  5. AI原生应用爆发:从通用大模型到垂直场景的算力重构
  6. C++ --- map和set的使用
  7. 【Linux】高性能网络模式:Reactor 反应堆模式
  8. 搞 PostgreSQL多才多艺的人--赵渝强 《PG数据库实战派》
  9. 【容器】设备上没有剩余空间的错误排查处理
  10. flutter WEB端启动优化(加载速度,加载动画)
  11. ubuntu虚拟机裁剪img文件系统
  12. WGAN的对偶性理解
  13. Mybatis源码分析
  14. 学习笔记--(7)
  15. Linux_RHCSA笔记①
  16. Vue+Elementui首页看板
  17. vue中使用geoscene无法出现弹窗
  18. Java项目实战--使用Java和LWJGL构建Minecraft风格游戏
  19. Java对象与JSON字符串的互转
  20. Docker学习--容器生命周期管理相关命令--rename 命令
  21. 江苏省委社会工作部部长等多人拟在省志愿服务联合会任职
  22. 重温经典|开播20周年,仙剑的那些幕后你知道吗?
  23. 印方称所有敌对行动均得到反击和回应,不会升级冲突
  24. 碧桂园境外债务重组:相当于现有公众票据本金额逾50%的持有人已加入协议
  25. 现场丨“影像上海”启幕:串联摄影、电影与当代艺术
  26. 万达电影:股东杭州臻希拟减持不超1.3927%公司股份