本文適合對有
Python
語言有一定基礎(chǔ)的人群,希望利用Python
做更多有意思的事情,比如搭建個(gè)人博客,記錄自己的所思所想,或者想找一個(gè)項(xiàng)目實(shí)踐前后端分離技術(shù)等等。跟著本文可以了解和運(yùn)行項(xiàng)目,本項(xiàng)目是在Window 10 Professional
系統(tǒng)下開發(fā)
大家好,我是落霞孤鶩
,上一篇介紹了開發(fā)博客的背景、技術(shù)棧,并介紹了如何搭建開發(fā)環(huán)境。這一篇介紹后端和前端的基礎(chǔ)框架代碼初始化,基于Django和Vue初始化項(xiàng)目框架代碼,跑通Hello world。
一、后端框架代碼搭建
后端 Python
代碼通過 PyCharm
能比較快速的搭建 Django
項(xiàng)目,因?yàn)樵?PyCharm
的專業(yè)版里面,已經(jīng)內(nèi)置了 Django
框架
1.1 通過 PyCharm
初始化 Django
項(xiàng)目
- 通過
pip
安裝Django
包
為了更好的兼容性,我們自己安裝 Django 2
版本,不采用最新版本。在命令行輸入如下命令:
pip install django==2.2.23
- 在
PyCharm
的首屏界面,點(diǎn)擊New Project
對話框,在左側(cè)選擇Django
,在右側(cè)的Location
中選擇項(xiàng)目地址,項(xiàng)目命令為Blog
并將我們之前安裝的Python
路徑選擇為Interpreter
,如下圖:
<img src="https://gitee.com/Zhou_Jimmy/images/raw/master/img/image-20210717165800189.png" alt="image-20210717165800189"/>
- 點(diǎn)擊Create,等待
PyCharm
執(zhí)行創(chuàng)建。
如果選擇的
Python Interpreter
環(huán)境中沒有安裝Django
,PyCharm
會自動安裝Django
最新版本,由于我們已經(jīng)安裝了Django,PyCharm
會自動使用環(huán)境中的Django
版本
完成后左側(cè)的導(dǎo)航區(qū)域會自動生成Django框架項(xiàng)目所需的文件,結(jié)構(gòu)如下圖:
- 在
Pycharm
右下角點(diǎn)擊Terminal
,通過pip
安裝Django Rest Framework
pip install djangorestframework==3.12.4
- 驗(yàn)證框架是否可以運(yùn)行
運(yùn)行點(diǎn)擊 PyCharm
右上角的運(yùn)行按鈕,如果正常,在PyCharm的運(yùn)行控制臺會打印如下信息
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
,回車,如下圖,說明框架搭建成功
1.2 配置 Django Rest Framework
-
啟用
Django Rest Framework
在
Blog
文件夾下,打開settings.py
文件,在INSTALLED_APPS
的list
中增加rest_framework
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', ]
在
settings.py
中增加Rest Framework
的配置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
1.3 配置 Sqlite
數(shù)據(jù)庫
- 在項(xiàng)目路徑下,創(chuàng)建data文件夾
- 在
settings.py
中修改DATABASES
中default
下的NAME
的值,增加data
路徑,接入如下
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'data/db.sqlite3'),
}
}
1.4 調(diào)整項(xiàng)目結(jié)構(gòu)
- 修改
Blog
文件夾名稱為project
通過 PyCharm
自動生成的項(xiàng)目結(jié)構(gòu),會自動生成一個(gè)和項(xiàng)目名稱一樣的子文件夾,為了有效的組織后端的各個(gè)模塊,這里我們將自動生成的 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%;" />
點(diǎn)擊 Refector
,然后點(diǎn)擊左下角的 Do Refector
完成修改。
<img src="https://gitee.com/Zhou_Jimmy/images/raw/master/img/image-20210716174553811.png" alt="image-20210716174553811" style="zoom:50%;" />
- 在
settings.py
文件中,將ROOT_URLCONF
中的Blog
修改為project
ROOT_URLCONF = 'project.urls'
- 在
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',
],
},
},
]
- 創(chuàng)建
common
APP,在terminal
中輸入如下命令:
python manage.py startapp common
- 完成后,整個(gè)項(xiàng)目結(jié)構(gòu)如下圖:
1.5 編寫 User
對象的 API
- 在
common/models.py
中編寫基礎(chǔ)模型抽象類AbstractBaseModel
用來幫助構(gòu)建所有業(yè)務(wù)模型自動增加創(chuàng)建人,創(chuàng)建時(shí)間,修改人,修改時(shí)間
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
其中兩個(gè)屬性的入?yún)⑿枰f明
auto_now_add=True
表示在新增的時(shí)候,自動將該字段的值設(shè)置為當(dāng)前時(shí)間auto_now=True
表示在記錄更新的時(shí)候,自動設(shè)置為當(dāng)前時(shí)間abstract = True
表示該類是抽象類,不需要生成物理模型
- 在
common/models.py
中重寫User
類
由于我們需要在博客中記錄注冊用戶的昵稱,頭像等擴(kuò)展信息,因此 Django
自帶的User
模型字段無法滿足,所以通過集集成Django
提供的 AbstractUser
來擴(kuò)展,通過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'
如果我們不單獨(dú)定義,則會用
Django
中設(shè)定的表名,這樣不利于我們有效的識別和管理數(shù)據(jù)庫中的表
- 在
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
接口中出現(xiàn)的字段,包括新增、修改、查詢接口字段。
- 在
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 三個(gè)類屬性,查詢集合 queryset
、序列器類 serialiazer_class
,權(quán)限校驗(yàn) permission_classes
。
我們這里設(shè)置權(quán)限校驗(yàn)為 AllowAny
,表示這個(gè)對象下的接口可以不用登錄就可以訪問,這么做的目的是為了下面測試接口的連通性。
- 修改
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
鑒權(quán)對應(yīng)的模型,因?yàn)槲覀兏膶懙哪J(rèn)的 User
表
# User
AUTH_USER_MODEL = 'common.User'
- 定義 API 路由規(guī)則
在 common
下新增urls.py
中,并增加如下代碼,這里需要定義 app_name = 'common'
,用于路由 Rest Framework
區(qū)別路由
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
用戶鑒權(quán)路由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 模型遷移和配置
- 通過
Django
做模型遷移
在 PyCharm
提供的 Terminal
中輸入如下命令,完成模型創(chuàng)建
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
- 配置數(shù)據(jù)庫管理工具
這個(gè)時(shí)候,可以在 data
文件下看到生成的 Sqlite
數(shù)據(jù)庫文件 db.sqlite3
,和我們在 project/settings.py
的 DATABASE
中定義的名稱一致。
雙擊這個(gè)文件,PyCharm 會自動在右側(cè)的 Database
工具類中創(chuàng)建一個(gè) Sqlite
的數(shù)據(jù)庫記錄。點(diǎn)擊下圖中表紅的按鈕,進(jìn)入數(shù)據(jù)庫配置頁面。
點(diǎn)擊下方的 Download missing driver files
,下載 Sqlite
驅(qū)動,修改 name
為 blog
,在Schemas
標(biāo)簽頁中,勾選 All shemas
,點(diǎn)擊確定。
然后右側(cè)就出現(xiàn)了我們剛剛通過 migrate
命令生成的表:
標(biāo)紅的表就是我們在 common/models.py
中定義的 User
類映射出來的表,其他的表是 Django
框架內(nèi)置的表,主要用在管理權(quán)限,Session
,日志等。
1.7 創(chuàng)建管理員賬號
這里通過 Django
自帶的命令完成管理員賬號的創(chuàng)建,在 PyCharm 提供的 Terminal 中,輸入如下命令:
python manage.py createsuperuser --email admin@example.com --username blog-admin
# Password:
# Password (again):
# Superuser created successfully.
依據(jù)提示輸入密碼 12345678.Abc
,確認(rèn)輸入密碼,回車,完成管理員賬號的創(chuàng)建
1.8 測試API
- 點(diǎn)擊 PyCharm 右上角的運(yùn)行按鈕
- 打開瀏覽器,在地址欄中輸入
http://127.0.0.1:8000/
看到如下界面,說明API配置已經(jīng)成功
- 測試用戶查詢接口
點(diǎn)擊上圖中的 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/"
}
得到如下圖界面,說明接口已經(jīng)完全編寫成功,恭喜你,記得給你自己一個(gè)大拇指哦
1.9 Django Rest Framework
官方英文示例教程
https://www.django-rest-framework.org/tutorial/quickstart/
二、前端框架代碼搭建
在介紹篇,我們已經(jīng)安裝了 Vite
,這里我們就通過 Vite
來初始化 Vue
的項(xiàng)目
2.1 通過 Vite
初始化 Vue
項(xiàng)目
- 在
C:\Users\Administrator
路徑下,創(chuàng)建文件夾VSCodeProjects
cd C:\Users\Administrator
mkdir VSCodeProjects
- 在
VscodeProjects
文件夾下創(chuàng)建blog
項(xiàng)目
cd VSCodeProjects
yarn create vite blog --template vue-ts
- 用
VS Code
項(xiàng)目
打開 C:\Users\Administrator\VSCodeProjects\Blog
文件夾,可以看到,通過 Vite
模板,已經(jīng)幫我們生成好了所有基礎(chǔ)文件,包括 TypeScript
相關(guān)的依賴和 shims
文件。
2.2 依賴安裝
- 安裝
Less
依賴
這里的 -D
參數(shù)表示是在開發(fā)階段的依賴,上線運(yùn)行時(shí)不需要該依賴。
yarn add less@4.1.1 -D
- 安裝
Element-Plus
依賴
yarn add element-plus
- 安裝基礎(chǔ)依賴,并運(yùn)行
在 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/
- 在瀏覽器中輸入地址
http://localhost:3000/
, 效果如下
三、前后端代碼聯(lián)調(diào)
前后端聯(lián)調(diào)時(shí),需要先在前端配置路由,Vite
代理,Axios
網(wǎng)絡(luò)請求。
3.1 配置 Axios
- 安裝
Axios
,在 VS Code 的Terminal 中執(zhí)行命令
yarn add axios
- 配置
vite.config.ts
在項(xiàng)目根目錄下,修改 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,
},
},
}
});
- 配置
Axios
實(shí)例
在 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;
- 編寫請求接口的代碼
在 api
下新建文件 service.ts
,編寫如下代碼:
import request from "./index";
export function getUserList(params: any) {
return request({
url: '/user/',
method: 'get',
params,
})
}
3.2 創(chuàng)建用戶列表頁面
修改在 src
下創(chuàng)建 App.vue
,在文件里面編寫如下代碼,獲取用戶列表的接口調(diào)用,調(diào)用后得到的數(shù)據(jù)加載到表格中展示,同時(shí)通過分頁展示列表。
<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="狀態(tài)" 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
- 安裝
vue-router
,在 VS Code 的Terminal 中執(zhí)行命令
yarn add vue-router@next
- 配置
route
在項(xiàng)目 src
目錄下面新建 route
目錄,并添加 index.ts
文件,文件中添加以下內(nèi)容
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 調(diào)整 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 測試界面
- 在 PyCharm 中啟動后端服務(wù)
- 在 VS Code 中啟動前端
yarn dev
- 在瀏覽器中輸入
http://127.0.0.1:8080
得到如下效果
到這一步,我們已經(jīng)完成了前后端聯(lián)調(diào),第一個(gè)接口已經(jīng)通過界面方式完成調(diào)用和數(shù)據(jù)展示,給自己一個(gè)贊哦。
四、代碼納入Git
版本管理
還記得我們在第一篇文章中創(chuàng)建的代碼倉庫吧,現(xiàn)在我們要把剛剛創(chuàng)建的前端代碼和后臺代碼提交到代碼倉庫中。
這里以后端為例,我之前是在Gitee上創(chuàng)建了一個(gè)公開倉庫:https://gitee.com/Zhou_Jimmy/blog-backend.git
,現(xiàn)在就把后端代碼提交到這個(gè)倉庫中。
命令在 PyCharm 提供的 Terminal 中輸入
4.1 配置本地的 git
信息
git config --global user.name "Zhou_Jimmy"
git config --global user.email "331352343@qq.com"
在設(shè)置的時(shí)候記得修改成你自己的名字和郵箱哦
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
在設(shè)置的時(shí)候,記得修改成你自己的倉庫地址
4.3 拉取遠(yuǎn)程倉庫上的代碼
git pull origin master
4.4 建立忽略文件
在項(xiàng)目根路徑下增加或編輯 .gitignore
文件,忽略不用加入到版本管理的文件,文件中的內(nèi)容可以參考 Gitee 或 GitHub 提供的模板,這里主要增加 PyCharm 配置信息的文件夾
.idea
如果是前端代碼,則增加這么一行
.vscode
4.5 提交代碼
4.5.1 通過 Git
命令提交
可以通過如下命令完成提交,最后需要你輸入倉庫賬號和密碼,完成后,代碼就提交到了遠(yuǎn)程倉庫了。
git add .
git commit -m "Django框架初始化代碼提交"
git push origin master
4.5.2 通過 PyCharm 界面功能提交
可以點(diǎn)擊 PyCharm 右上角的提交按鈕
點(diǎn)擊后,左側(cè)出現(xiàn)提交文件選擇框,勾選文件,并填寫comment
,點(diǎn)擊 Commit and Push
按鈕,完成提交。
后端提交完成后,遠(yuǎn)程倉庫效果如下:
前端提交完成后,遠(yuǎn)程倉庫效果如下: