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