Vue3+TypeScript+Django Rest Framework 搭建个人博客(一):框架代码初始化

本文适合对有 Python 语言有一定基础的人群,希望利用 Python 做更多有意思的事情,比如搭建个人博客,记录自己的所思所想,或者想找一个项目实践前后端分离技术等等。跟着本文可以了解和运行项目,本项目是在 Window 10 Professional 系统下开发

大家好,我是落霞孤鹜,上一篇介绍了开发博客的背景、技术栈,并介绍了如何搭建开发环境。这一篇介绍后端和前端的基础框架代码初始化,基于Django和Vue初始化项目框架代码,跑通Hello world。

一、后端框架代码搭建

后端 Python 代码通过 PyCharm 能比较快速的搭建 Django 项目,因为在 PyCharm 的专业版里面,已经内置了 Django 框架

1.1 通过 PyCharm 初始化 Django 项目

  1. 通过 pip 安装Django

为了更好的兼容性,我们自己安装 Django 2 版本,不采用最新版本。在命令行输入如下命令:

pip install django==2.2.23
  1. PyCharm 的首屏界面,点击 New Project 对话框,在左侧选择 Django,在右侧的 Location中选择项目地址,项目命令为Blog 并将我们之前安装的 Python 路径选择为 Interpreter ,如下图:

<img src="https://gitee.com/Zhou_Jimmy/images/raw/master/img/image-20210717165800189.png" alt="image-20210717165800189"/>

  1. 点击Create,等待 PyCharm 执行创建。

如果选择的 Python Interpreter 环境中没有安装 DjangoPyCharm 会自动安装 Django 最新版本,由于我们已经安装了Django,PyCharm 会自动使用环境中的 Django 版本

完成后左侧的导航区域会自动生成Django框架项目所需的文件,结构如下图:

image-20210717170550892
  1. Pycharm 右下角点击 Terminal,通过 pip 安装 Django Rest Framework
pip install djangorestframework==3.12.4
  1. 验证框架是否可以运行

运行点击 PyCharm 右上角的运行按钮,如果正常,在PyCharm的运行控制台会打印如下信息

Performing system checks...

Watching for file changes with StatReloader
System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
July 17, 2021 - 17:42:28
Django version 2.2.23, using settings 'project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

打开 Edge 或 Chrome 浏览器,输入 http://127.0.0.1:8000,回车,如下图,说明框架搭建成功

image-20210717201616697

1.2 配置 Django Rest Framework

  1. 启用 Django Rest Framework

    Blog 文件夹下,打开 settings.py 文件,在 INSTALLED_APPSlist 中增加 rest_framework

    INSTALLED_APPS = [
        'django.contrib.admin',  
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'rest_framework',
    ]
    
  2. settings.py 中增加 Rest Framework 的配置

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}

1.3 配置 Sqlite 数据库

  1. 在项目路径下,创建data文件夹
  2. settings.py 中修改 DATABASESdefault 下的 NAME 的值,增加 data 路径,接入如下
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'data/db.sqlite3'),
    }
}

1.4 调整项目结构

  1. 修改 Blog 文件夹名称为 project

通过 PyCharm 自动生成的项目结构,会自动生成一个和项目名称一样的子文件夹,为了有效的组织后端的各个模块,这里我们将自动生成的 Blog 文件夹修改为 project

操作如图:

<img src="https://gitee.com/Zhou_Jimmy/images/raw/master/img/image-20210716174351302.png" alt="image-20210716174351302" style="zoom:50%;" />

<img src="https://gitee.com/Zhou_Jimmy/images/raw/master/img/image-20210716174434089.png" alt="image-20210716174434089" style="zoom:50%;" />

点击 Refector,然后点击左下角的 Do Refector 完成修改。

<img src="https://gitee.com/Zhou_Jimmy/images/raw/master/img/image-20210716174553811.png" alt="image-20210716174553811" style="zoom:50%;" />

  1. settings.py 文件中,将 ROOT_URLCONF 中的 Blog 修改为 project
ROOT_URLCONF = 'project.urls'
  1. settings.py 文件中,将 TEMPLATES 中的 DIRS 的值修改为 [BASE_DIR + '/templates']
TEMPLATES = [    
  {        
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR + '/templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
      },
  },
]
  1. 创建 common APP,在 terminal 中输入如下命令:
python manage.py startapp common
  1. 完成后,整个项目结构如下图:
image-20210717173357712

1.5 编写 User 对象的 API

  1. common/models.py 中编写基础模型抽象类 AbstractBaseModel

用来帮助构建所有业务模型自动增加创建人,创建时间,修改人,修改时间

from django.contrib.auth.models
import AbstractUserfrom django.db import models


class AbstractBaseModel(models.Model):
    creator = models.IntegerField('creator', null=True)
    created_at = models.DateTimeField(verbose_name='Created at', auto_now_add=True)

    modifier = models.IntegerField('modifier', null=True)
    modified_at = models.DateTimeField(verbose_name='Modified at', auto_now=True)

    class Meta:
        abstract = True

其中两个属性的入参需要说明

  • auto_now_add=True 表示在新增的时候,自动将该字段的值设置为当前时间

  • auto_now=True 表示在记录更新的时候,自动设置为当前时间

  • abstract = True 表示该类是抽象类,不需要生成物理模型

  1. common/models.py 中重写User

由于我们需要在博客中记录注册用户的昵称,头像等扩展信息,因此 Django 自带的User 模型字段无法满足,所以通过集集成Django 提供的 AbstractUser 来扩展,通过Meta类中定义我们想要的表名 blog_user

class User(AbstractUser, AbstractBaseModel):
    avatar = models.CharField('头像', max_length=1000, blank=True)
    nickname = models.CharField('昵称', null=True, blank=True, max_length=200)
    
    class Meta(AbstractUser.Meta):
        db_table = 'blog_user'
        swappable = 'AUTH_USER_MODEL'

如果我们不单独定义,则会用 Django 中设定的表名,这样不利于我们有效的识别和管理数据库中的表

  1. common 下新增 serializers.py ,在serializers.py 中新增类 UserSerialiazer,继承 Rest Framework 提供的 serializers.ModelSerializer
from rest_framework import serializers
from common.models import User


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'avatar', 'email', 'is_active', 'created_at',  'nickname']

这里定义需要在 API 接口中出现的字段,包括新增、修改、查询接口字段。

  1. common/views.py 文件中,编写 UserViewSet 类,继承 Rest Framework 提供的 viewsets.ModelViewSet
from rest_framework import viewsets, permissions
from common.models import User
from common.serializers import UserSerializer

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all().order_by('username')
    serializer_class = UserSerializer
    permission_classes = [permissions.AllowAny]

这里只需要 Override 三个类属性,查询集合 queryset、序列器类 serialiazer_class,权限校验 permission_classes

我们这里设置权限校验为 AllowAny,表示这个对象下的接口可以不用登录就可以访问,这么做的目的是为了下面测试接口的连通性。

  1. 修改 project/settings.py 配置

INSTALL_APPS 中增加 common

INSTALLED_APPS = [
    'django.contrib.admin',  
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'common',
]

新增一行代码,定义User 鉴权对应的模型,因为我们改写的默认的 User

# User
AUTH_USER_MODEL = 'common.User'
  1. 定义 API 路由规则

common 下新增urls.py 中,并增加如下代码,这里需要定义 app_name = 'common',用于路由 Rest Framework 区别路由

from rest_framework import routers
from django.urls import include, path
from common import views

router = routers.DefaultRouter()
router.register('user', views.UserViewSet)

app_name = 'common'

urlpatterns = [
    path('', include(router.urls)),
]

project/url 中引入 common APP中的路由,并加入 Rest Framework 用户鉴权路由api-auth/

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
        path('admin/', admin.site.urls),
    path('', include('common.urls', namespace='common')),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

1.6 模型迁移和配置

  1. 通过Django 做模型迁移

PyCharm 提供的 Terminal 中输入如下命令,完成模型创建

python manage.py makemigrations
# Migrations for 'common':
#  common\migrations\0001_initial.py
#    - Create model User
python manage.py migrate
# Operations to perform:
#   Apply all migrations: admin, auth, common, contenttypes, sessions
# Running migrations:
#   Applying contenttypes.0001_initial... OK
#   Applying contenttypes.0002_remove_content_type_name... OK
#   Applying auth.0001_initial... OK
#   Applying auth.0002_alter_permission_name_max_length... OK
#   Applying auth.0003_alter_user_email_max_length... OK
#   Applying auth.0004_alter_user_username_opts... OK
#   Applying auth.0005_alter_user_last_login_null... OK
#   Applying auth.0006_require_contenttypes_0002... OK
#   Applying auth.0007_alter_validators_add_error_messages... OK
#   Applying auth.0008_alter_user_username_max_length... OK
#   Applying auth.0009_alter_user_last_name_max_length... OK
#   Applying auth.0010_alter_group_name_max_length... OK
#   Applying auth.0011_update_proxy_permissions... OK
#   Applying common.0001_initial... OK
#   Applying admin.0001_initial... OK
#   Applying admin.0002_logentry_remove_auto_add... OK
#   Applying admin.0003_logentry_add_action_flag_choices... OK
#   Applying sessions.0001_initial... OK
  1. 配置数据库管理工具

这个时候,可以在 data 文件下看到生成的 Sqlite 数据库文件 db.sqlite3,和我们在 project/settings.pyDATABASE 中定义的名称一致。

image-20210717200523546

双击这个文件,PyCharm 会自动在右侧的 Database 工具类中创建一个 Sqlite 的数据库记录。点击下图中表红的按钮,进入数据库配置页面。

image-20210717195549453

点击下方的 Download missing driver files,下载 Sqlite 驱动,修改 nameblog,在Schemas 标签页中,勾选 All shemas,点击确定。

image-20210717195453923

然后右侧就出现了我们刚刚通过 migrate 命令生成的表:

image-20210717200126701

标红的表就是我们在 common/models.py 中定义的 User 类映射出来的表,其他的表是 Django 框架内置的表,主要用在管理权限,Session,日志等。

1.7 创建管理员账号

这里通过 Django 自带的命令完成管理员账号的创建,在 PyCharm 提供的 Terminal 中,输入如下命令:

python manage.py createsuperuser --email admin@example.com --username blog-admin
# Password:
# Password (again):
# Superuser created successfully.

依据提示输入密码 12345678.Abc,确认输入密码,回车,完成管理员账号的创建

1.8 测试API

  1. 点击 PyCharm 右上角的运行按钮
image-20210717201808127
  1. 打开浏览器,在地址栏中输入 http://127.0.0.1:8000/

看到如下界面,说明API配置已经成功

image-20210717201333539
  1. 测试用户查询接口

点击上图中的 http://127.0.0.1:8000/user/

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "user": "http://127.0.0.1:8000/user/"
}

得到如下图界面,说明接口已经完全编写成功,恭喜你,记得给你自己一个大拇指哦

image-20210717201959887

1.9 Django Rest Framework 官方英文示例教程

https://www.django-rest-framework.org/tutorial/quickstart/

二、前端框架代码搭建

在介绍篇,我们已经安装了 Vite,这里我们就通过 Vite 来初始化 Vue 的项目

2.1 通过 Vite 初始化 Vue 项目

  1. C:\Users\Administrator 路径下,创建文件夹 VSCodeProjects
cd C:\Users\Administrator
mkdir VSCodeProjects
  1. VscodeProjects 文件夹下创建 blog 项目
cd VSCodeProjects
yarn create vite blog --template vue-ts
  1. VS Code 项目

打开 C:\Users\Administrator\VSCodeProjects\Blog 文件夹,可以看到,通过 Vite 模板,已经帮我们生成好了所有基础文件,包括 TypeScript 相关的依赖和 shims 文件。

image-20210717223043228

2.2 依赖安装

  1. 安装 Less 依赖

这里的 -D 参数表示是在开发阶段的依赖,上线运行时不需要该依赖。

yarn add less@4.1.1 -D
  1. 安装 Element-Plus 依赖
yarn add element-plus
  1. 安装基础依赖,并运行

在 VS Code 中,通过快捷键 Ctrl + J 打开 Terminal,输入如下命令:

yarn
yarn dev
# yarn run v1.22.10
# warning package.json: No license field
# $ vite
# [vite] Optimizable dependencies detected:
# vue
# 
#   Dev server running at:
#   > Network:  http://192.168.2.14:3000/
#   > Local:    http://localhost:3000/
  1. 在浏览器中输入地址 http://localhost:3000/, 效果如下
image-20210717223231841

三、前后端代码联调

前后端联调时,需要先在前端配置路由,Vite 代理,Axios 网络请求。

3.1 配置 Axios

  1. 安装 Axios ,在 VS Code 的Terminal 中执行命令
yarn add axios
  1. 配置 vite.config.ts

在项目根目录下,修改 vite.config.ts,代码如下:

import vue from '@vitejs/plugin-vue'
import {defineConfig} from 'vite'


export default defineConfig({
    plugins: [
        vue(),
     ],

    base: '/',

    server: {
        host: "localhost",
        port: 3000,
        proxy: {
            '/api': {
                target: 'http://localhost:8000/',
                changeOrigin: true,
                ws: false,
                rewrite: (pathStr) => pathStr.replace('/api', ''),
                timeout: 5000,
            },
        },
    }
});
  1. 配置 Axios 实例

src 目录下,新建文件夹 api,在 api 下新建文件 index.ts,编写如下代码:

import axios, {AxiosRequestConfig, AxiosResponse} from "axios";

const request = axios.create({
    baseURL: import.meta.env.MODE !== 'production' ? '/api' : '',
})

export default request;
  1. 编写请求接口的代码

api 下新建文件 service.ts,编写如下代码:

import request from "./index";

export function getUserList(params: any) {
    return request({
        url: '/user/',
        method: 'get',
        params,
    })
}

3.2 创建用户列表页面

修改在 src 下创建 App.vue ,在文件里面编写如下代码,获取用户列表的接口调用,调用后得到的数据加载到表格中展示,同时通过分页展示列表。

<template>
  <div>
    <div>
      <el-table
        :data="state.userList"
        :header-cell-style="{ background: '#eef1f6', color: '#606266' }"
        stripe
      >
        <el-table-column type="selection" width="55" />
        <el-table-column label="ID" prop="id" width="80" />
        <el-table-column label="账号" prop="username" width="200" />
        <el-table-column label="昵称" prop="nickname" width="200" />
        <el-table-column label="状态" prop="is_active" />
      </el-table>
    </div>
    <div class="pagination">
      <el-pagination
        :page-size="10"
        :total="state.total"
        background
        layout="prev, pager, next"
      ></el-pagination>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive } from "vue";
import { getUserList } from "./api/service";

export default defineComponent({
  name: "App",
  setup: function () {
    const state = reactive({
      userList: [],
      params: {
        page: 1,
        page_size: 10,
      },
      total: 0,
    });

    const handleSearch = async (): Promise<void> => {
      try {
        const data: any = await getUserList(state.params);
        state.userList = data.data.results;
        state.total = data.data.count;
      } catch (e) {
        console.error(e);
      }
    };

    handleSearch();
    return {
      state,
      handleSearch,
    };
  },
});
</script>

<style scoped>
.pagination {
  text-align: right;
  margin-top: 12px;
}
</style>

3.3 配置 Router

  1. 安装 vue-router ,在 VS Code 的Terminal 中执行命令
yarn add vue-router@next
  1. 配置 route

在项目 src 目录下面新建 route 目录,并添加 index.ts 文件,文件中添加以下内容

import {createRouter, createWebHistory, RouteRecordRaw} from "vue-router";
import App from "../App.vue";

const routes: Array<RouteRecordRaw> = [
    {
        path: "/",
        name: "User",
        component: App,
        meta: {}
    },
]

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes,
});


export default router;

3.4 调整 main.ts

增加 Element-Plus的组件,加载 router,代码如下:

import { createApp } from 'vue'
import App from './App.vue'
import router from "./route";
import {
    ElPagination,
    ElTable,
    ElTableColumn
} from 'element-plus';

const app = createApp(App)

app.component(ElTable.name, ElTable);
app.component(ElTableColumn.name, ElTableColumn);
app.component(ElPagination.name, ElPagination);


app.use(router).mount('#app')

3.5 测试界面

  1. 在 PyCharm 中启动后端服务
  2. 在 VS Code 中启动前端
yarn dev
  1. 在浏览器中输入http://127.0.0.1:8080 得到如下效果
image-20210718175955373

到这一步,我们已经完成了前后端联调,第一个接口已经通过界面方式完成调用和数据展示,给自己一个赞哦。

四、代码纳入Git 版本管理

还记得我们在第一篇文章中创建的代码仓库吧,现在我们要把刚刚创建的前端代码和后台代码提交到代码仓库中。

这里以后端为例,我之前是在Gitee上创建了一个公开仓库:https://gitee.com/Zhou_Jimmy/blog-backend.git,现在就把后端代码提交到这个仓库中。

命令在 PyCharm 提供的 Terminal 中输入

4.1 配置本地的 git 信息

git config --global user.name "Zhou_Jimmy"
git config --global user.email "331352343@qq.com"

在设置的时候记得修改成你自己的名字和邮箱哦

4.2 本地代码初始化git

git init
# Initialized empty Git repository in C:/Users/Administrator/PycharmProjects/Blog/.git/
git remote add origin https://gitee.com/Zhou_Jimmy/blog-backend.git

在设置的时候,记得修改成你自己的仓库地址

4.3 拉取远程仓库上的代码

git pull origin master

4.4 建立忽略文件

在项目根路径下增加或编辑 .gitignore 文件,忽略不用加入到版本管理的文件,文件中的内容可以参考 Gitee 或 GitHub 提供的模板,这里主要增加 PyCharm 配置信息的文件夹

.idea

如果是前端代码,则增加这么一行

.vscode

4.5 提交代码

4.5.1 通过 Git 命令提交

可以通过如下命令完成提交,最后需要你输入仓库账号和密码,完成后,代码就提交到了远程仓库了。

git add .
git commit -m "Django框架初始化代码提交"
git push origin master

4.5.2 通过 PyCharm 界面功能提交

可以点击 PyCharm 右上角的提交按钮

image-20210717205924922

点击后,左侧出现提交文件选择框,勾选文件,并填写comment,点击 Commit and Push 按钮,完成提交。

image-20210717210041771

后端提交完成后,远程仓库效果如下:

image-20210717210532928

前端提交完成后,远程仓库效果如下:

image-20210718181424047
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容