目录
[1. 环境搭建与项目初始化](#1. 环境搭建与项目初始化)
[2. 数据库模型设计](#2. 数据库模型设计)
[3. 后端API开发 (Django REST Framework)](#3. 后端API开发 (Django REST Framework))
[4. 前端实现 (Vue 3)](#4. 前端实现 (Vue 3))
[5. 访问统计实现](#5. 访问统计实现)
[6. 部署与优化](#6. 部署与优化)
1. 环境搭建与项目初始化
后端 (Django)
-
创建Django项目
bashdjango-admin startproject blog_backend cd blog_backend python manage.py startapp blog
-
安装依赖
bashpip install django djangorestframework django-cors-headers djangorestframework-simplejwt mysqlclient
-
配置MySQL数据库
修改
settings.py
:pythonDATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'blog_db', 'USER': 'root', 'PASSWORD': 'your_password', 'HOST': 'localhost', 'PORT': '3306', } }
-
配置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)
用户注册/登录
-
序列化器 (
serializers.py
)pythonfrom 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
-
视图 (
views.py
)pythonfrom 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)
文章发布与搜索
-
文章序列化器
pythonclass ArticleSerializer(serializers.ModelSerializer): class Meta: model = Article fields = '__all__'
-
文章搜索接口
使用Django ORM的全文搜索:
pythonclass 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
核心功能实现
-
Markdown渲染
使用
marked
或vue-markdown
库:html<template> <div v-html="compiledMarkdown"></div> </template> <script setup> import { marked } from 'marked' const compiledMarkdown = marked(props.content) </script>
-
富文本编辑器集成 (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>
-
动态路由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
-
创建访问记录模型
pythonclass 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)
-
中间件统计访问量
pythonclass 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. 部署与优化
-
MySQL全文索引查询优化
确保MySQL版本 >= 5.6,并配置索引:
sqlCREATE FULLTEXT INDEX ft_idx ON blog_article(title, content);
-
Nginx配置反向代理
sqlserver { 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; } }
-
性能优化
-
使用
django-debug-toolbar
分析查询 -
Vue路由懒加载:
javascriptconst routes = [ { path: '/article/:id', component: () => import('./views/ArticleDetail.vue') } ]
-
关键问题解决
-
跨域配置
使用
django-cors-headers
,确保前端能访问后端API。 -
树形评论渲染
前端递归组件实现:
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>
-
JWT Token自动刷新
使用Axios拦截器:
javascriptaxios.interceptors.response.use(response => response, error => { if (error.response.status === 401) { return refreshToken().then(() => { return axios(error.config) }) } return Promise.reject(error) })
通过以上步骤,你可以逐步搭建一个功能完整的博客系统。建议先从基础功能(如文章发布)开始,逐步迭代添加评论、搜索等模块。