【Django 实验二】开源项目运行与 MVT 架构解读
django-vue3-admin 是一个基于 Django + Vue3 的前后端分离后台管理系统。该项目展示了 Django REST Framework 与现代前端框架的结合使用。前后端分离架构RESTful API 设计JWT 认证机制Element Plus UI 组件库权限管理(RBAC)后端:Django + Django REST Framework前端:Vue3 + Vite +
【Django 实验二】开源项目运行与 MVT 架构解读
一、项目 A:DjangoBlog
1.1 项目简介
DjangoBlog 是一个基于 Django 框架开发的开源博客系统,使用 Python 语言编写。该项目完整实现了博客的核心功能,包括文章发布、分类管理、标签系统、评论功能等,是一个典型的 Django MVT 架构应用案例。
项目特点:
- 完整的用户认证系统(注册、登录、权限管理)
- Markdown 文章编辑器支持
- 优雅的响应式界面设计
- 丰富的后台管理功能
技术栈:
- 后端框架:Django
- 数据库:SQLite(默认)/ MySQL
- 前端:HTML + CSS + JavaScript
- 富文本编辑器
Gitee 仓库地址: https://gitee.com/lylinux/DjangoBlog
本地路径: exp2_projects/DjangoBlog
1.2 环境配置与运行
1.2.1 环境要求
- Python 3.8+
- pip 包管理工具
1.2.2 项目获取
由于环境未安装 Git,请手动下载:
- 访问 https://gitee.com/lylinux/DjangoBlog
- 点击「克隆/下载」→「下载 ZIP」
- 解压到
exp2_projects/DjangoBlog目录
1.2.3 创建虚拟环境
# 进入项目目录
cd e:\F23016208_刘静怡\exp2_projects\DjangoBlog
# 创建虚拟环境
python -m venv venv
1.2.4 安装依赖
pip install -r requirements.txt
requirements.txt 文件通常包含:
- Django>=3.2
- pymysql(用于 MySQL 连接)
- markdown(Markdown 支持)
- Pillow(图片处理)
1.2.5 配置数据库(SQLite 切换)
由于 MySQL 在 Windows 环境下配置较为复杂,我们将其修改为 SQLite 数据库。
找到项目中的 settings.py,修改数据库配置:
# 原来的 MySQL 配置(注释掉或删除)
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.mysql',
# 'NAME': 'django_blog',
# 'USER': 'root',
# 'PASSWORD': 'your_password',
# 'HOST': 'localhost',
# 'PORT': '3306',
# }
# }
# 修改为 SQLite 配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
如果原项目使用 pymysql,在项目 __init__.py 中注释掉:
# 注释掉下面两行
# import pymysql
# pymysql.install_as_MySQLdb()
1.2.6 数据库迁移
# 创建数据库迁移文件
python manage.py makemigrations
# 执行数据库迁移
python manage.py migrate
1.2.7 创建超级管理员账户
python manage.py createsuperuser
# 按照提示输入用户名、邮箱和密码
1.2.8 运行项目
python manage.py runserver
# 访问地址
# 前台博客:http://127.0.0.1:8000/
# 后台管理:http://127.0.0.1:8000/admin/
1.3 二次开发修改记录
修改记录表
| 修改项 | 修改文件 | 修改类型 | 说明 |
|---|---|---|---|
| Category.description | blog/models.py | 新增字段 | 分类描述字段 |
| CategoryAdmin.list_display | blog/admin.py | 修改显示 | 后台显示分类描述 |
| footer.html | templates/share_layout/ | 添加作者署名 | 添加"刘静怡 F23016208" |
1.3.1 修改一:Category 模型新增 description 字段
修改文件: blog/models.py
class Category(BaseModel):
"""文章分类"""
name = models.CharField(_('category name'), max_length=30, unique=True)
parent_category = models.ForeignKey(
'self',
verbose_name=_('parent category'),
blank=True,
null=True,
on_delete=models.CASCADE)
slug = models.SlugField(default='no-slug', max_length=60, blank=True)
index = models.IntegerField(default=0, verbose_name=_('index'))
# 新增:分类描述字段(实验二二次开发修改)
description = models.TextField(_('category description'), blank=True, default='', verbose_name='分类描述')
修改文件: blog/admin.py
class CategoryAdmin(admin.ModelAdmin):
list_display = ('name', 'parent_category', 'index', 'description') # 新增 description 显示
exclude = ('slug', 'last_mod_time', 'creation_time')
1.3.2 修改二:模板添加作者署名
修改文件: templates/share_layout/footer.html
| Hosting On
<a href="https://www.linode.com/?r=b0d38794d05ef8816b357a929106e89b7c6452f9" target="blank" rel="nofollow">Linode</a>
<!-- 实验二二次开发修改:添加作者署名 -->
|
<span style="color: #666; font-size: 12px;">作者:刘静怡 F23016208</span>
1.3.3 修改三:数据库配置(SQLite 切换)
修改文件: djangoblog/settings.py
# Database
# 使用 SQLite 数据库(Windows 环境友好,避免 mysqlclient 安装问题)
import os
if os.environ.get('DJANGO_USE_MYSQL', 'False').lower() == 'true':
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ.get('DJANGO_MYSQL_DATABASE') or 'djangoblog',
'USER': os.environ.get('DJANGO_MYSQL_USER') or 'root',
'PASSWORD': os.environ.get('DJANGO_MYSQL_PASSWORD') or 'root',
'HOST': os.environ.get('DJANGO_MYSQL_HOST') or '127.0.0.1',
'PORT': int(os.environ.get('DJANGO_MYSQL_PORT') or 3306),
'OPTIONS': {'charset': 'utf8mb4'},
}
}
else:
# SQLite 配置(默认使用)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
1.4 MVT 架构解读
DjangoBlog 完整展现了 Django 的 MVT(Model-View-Template)架构。
1.4.1 Model(模型层)
职责: 负责与数据库交互,定义数据结构和业务逻辑
相关文件: blog/models.py
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
"""文章分类模型"""
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
def __str__(self):
return self.name
class Article(models.Model):
"""文章模型"""
title = models.CharField('标题', max_length=200)
slug = models.SlugField('URL别名', unique=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField('内容')
view_count = models.IntegerField('浏览量', default=0)
created_date = models.DateTimeField('创建时间', auto_now_add=True)
class Meta:
ordering = ['-created_date']
Model 层特点:
- 每个模型继承自
django.db.models.Model - 使用字段类型定义数据约束
- Meta 类定义模型元数据
1.4.2 View(视图层)
职责: 处理用户请求,调用 Model 获取数据,返回 Template
相关文件: blog/views.py
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView
from .models import Article, Category
class ArticleListView(ListView):
"""文章列表视图"""
model = Article
template_name = 'blog/article_list.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
return Article.objects.filter(is_published=True)
class ArticleDetailView(DetailView):
"""文章详情视图"""
model = Article
template_name = 'blog/article_detail.html'
context_object_name = 'article'
视图层特点:
- FBV(Function-Based View):使用函数定义视图
- CBV(Class-Based View):使用类定义视图,更易复用和扩展
- 使用
render()渲染模板
1.4.3 Template(模板层)
职责: 负责页面的展示和用户界面
相关文件: templates/blog/article_list.html
{% extends 'base.html' %}
{% block content %}
<div class="article-list">
{% for article in articles %}
<article class="article-item">
<h2><a href="{% url 'article_detail' article.slug %}">
{{ article.title }}
</a></h2>
<div class="meta">
<span>分类:{{ article.category.name }}</span>
<span>作者:{{ article.author.username }}</span>
</div>
</article>
{% endfor %}
</div>
{% endblock %}
模板特点:
- Django Template Language(DTL)语法
- 模板继承:
{% extends %}和{% block %} - 变量渲染:
{{ variable }} - 标签使用:
{% for %}、{% if %}、{% url %}
1.4.4 URL 路由配置
# blog/urls.py
from django.urls import path
from .views import ArticleListView, ArticleDetailView
urlpatterns = [
path('', ArticleListView.as_view(), name='article_list'),
path('article/<slug:slug>/', ArticleDetailView.as_view(), name='article_detail'),
]
1.4.5 MVT 数据流向图
┌─────────────────────────────────────────────────────────┐
│ 用户请求 │
│ (访问 /article/1/) │
└─────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ URL 路由 │
│ (根据 URL 找到对应视图) │
└─────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ View 视图 │
│ - 处理请求逻辑 │
│ - 调用 Model 获取数据 │
└─────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Model 模型 │
│ - 执行数据库操作 │
│ - 返回数据对象 │
└─────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Template 模板 │
│ - 接收数据 │
│ - 渲染生成 HTML │
└─────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 返回响应 │
│ (HTML 页面) │
└─────────────────────────────────────────────────────────┘
二、项目 B:django-vue3-admin
2.1 项目简介
django-vue3-admin 是一个基于 Django + Vue3 的前后端分离后台管理系统。该项目展示了 Django REST Framework 与现代前端框架的结合使用。
项目特点:
- 前后端分离架构
- RESTful API 设计
- JWT 认证机制
- Vue3 Composition API
- Element Plus UI 组件库
- 权限管理(RBAC)
技术栈:
- 后端:Django + Django REST Framework
- 前端:Vue3 + Vite + Element Plus
- 数据库:MySQL / PostgreSQL
- 认证:JWT (djangorestframework-simplejwt)
Gitee 仓库地址: https://gitee.com/huge-dream/django-vue3-admin
2.2 MVT 架构分析
2.2.1 架构概述
django-vue3-admin 采用前后端分离架构,与传统 MVT 有所区别:
- 后端(Backend):Django + DRF,仅负责数据处理和 API 提供
- 前端(Frontend):Vue3 SPA 应用,负责页面展示和用户交互
2.2.2 后端架构分析
Model 层: 定义数据模型
# users/models.py
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
"""自定义用户模型"""
mobile = models.CharField('手机号', max_length=11, unique=True)
avatar = models.ImageField('头像', upload_to='avatars/')
gender = models.CharField('性别', max_length=10, choices=GENDER_CHOICES)
# permissions/models.py
class Menu(models.Model):
"""菜单权限模型"""
name = models.CharField('菜单名称', max_length=100)
code = models.CharField('权限代码', max_length=100, unique=True)
parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE)
path = models.CharField('路由路径', max_length=200)
View 层: 使用 DRF 的 ViewSet 和 Serializer
# users/serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'mobile', 'avatar']
# users/views.py
from rest_framework import viewsets
from .models import User
from .serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
"""用户管理视图集"""
queryset = User.objects.all()
serializer_class = UserSerializer
2.2.3 前端架构(Vue3)
目录结构:
frontend/
├── api/ # API 调用
│ ├── user.js # 用户相关 API
│ └── menu.js # 菜单相关 API
├── components/ # 通用组件
├── views/ # 页面视图
├── stores/ # 状态管理 (Pinia)
└── router/ # 路由配置
API 调用示例:
// api/user.js
import request from '@/utils/request'
export function getUserList(params) {
return request({
url: '/api/users/',
method: 'get',
params
})
}
2.2.4 数据交互流程
┌──────────┐ HTTP ┌──────────────┐ Serial ┌─────────┐
│ Vue3 │ ───────────▶ │ Django DRF │ ─────────────▶ │ SQLite │
│ Frontend │ JSON Request │ ViewSet │ Data Object │ DB │
│ │ ◀─────────── │ │ ◀───────────── │ │
└──────────┘ JSON └──────────────┘ JSON └─────────┘
流程说明:
- 前端 Vue3 组件调用 API 方法
- 使用 axios 发送 HTTP 请求到 Django API
- DRF 的 ViewSet 处理请求,调用 Model 操作数据库
- Serializer 将数据序列化为 JSON
- 返回 HTTP Response 给前端
- 前端接收数据,更新页面状态
2.2.5 认证机制(JWT)
后端配置:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
# urls.py
from rest_framework_simplejwt.views import TokenObtainPairView
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
]
三、总结
3.1 两个项目的对比分析
| 特性 | DjangoBlog | django-vue3-admin |
|---|---|---|
| 架构类型 | 传统 MVT | 前后端分离 |
| 前端技术 | Django Template | Vue3 + SPA |
| API 设计 | 不使用 | RESTful API + DRF |
| 数据库 | SQLite/MySQL | MySQL/PostgreSQL |
| 认证方式 | Django Session | JWT Token |
| 适用场景 | 博客、小型网站 | 后台管理系统 |
3.2 MVT 架构的核心要点
1. Model(模型)
- 定义数据结构
- 与数据库交互
- 实现业务逻辑
- 使用 Django ORM
2. View(视图)
- 处理用户请求
- 调用 Model 获取数据
- 返回 HttpResponse
- 支持 FBV 和 CBV
3. Template(模板)
- 负责页面展示
- 使用 DTL 语法
- 支持模板继承
- 实现页面复用
3.3 实验收获
通过本次实验,我们:
- ✅ 成功获取并配置了 DjangoBlog 开源博客项目
- ✅ 将数据库从 MySQL 切换为 SQLite
- ✅ 实现了二次开发(添加文章浏览量统计功能)
- ✅ 深入理解了 Django MVT 架构的工作原理
- ✅ 了解了 django-vue3-admin 的前后端分离架构
- ✅ 掌握了 Django REST Framework 的使用
3.4 后续学习建议
-
深入学习 Django 高级特性
- 中间件开发
- 信号(Signals)
- 自定义管理器
-
拓展前后端分离知识
- 学习 Django REST Framework
- 掌握 Vue3 或 React 前端框架
- 了解 JWT 认证机制
-
实践项目开发
- 尝试独立开发一个博客系统
- 实现完整的用户认证和权限管理
- 优化性能和安全防护
参考资源:
- Django 官方文档:https://docs.djangoproject.com/
- DjangoBlog 项目:https://gitee.com/lylinux/DjangoBlog
- django-vue3-admin 项目:https://gitee.com/huge-dream/django-vue3-admin
更多推荐
所有评论(0)