Web 开发的洪流已经不可阻挡地向前后端分离驶去。
Web 后端在主流场景下,注定成为了仅仅提供 API 接口和进行一些需要消耗服务器性能和后端计算载体;
而 Web 前端的洪流,又不可避免地走向了「前端工程化」、「模块化」和「单页应用开发」,以前那种直接修改 HTML、CSS、JS 文件的开发方式,不可避免地要成为小众。
今天,州的先生就用一个 Django Vue 的组合,快速实现一个前后端分离的单页用户登录 Web 应用,以供大家参考。
所选用的框架有:
- Django 2.2
- django-cors-headers
- Django REST framework
- PearAdminAnt(Vue3)
开始吧!
构建 Django 认证后端
首先,我们来构建一个 Django 的认证后端,用于用户注册、登录、认证的处理。
在这里,我们使用的是 Django 自带的用户模型。
安装模块
首先,安装 Django 和 DRF:
代码语言:javascript复制pip install django==2.2
pip install djangorestframework
创建项目和应用
然后,创建一个 Django 项目:
代码语言:javascript复制django-admin startproject UserBackend
接着进入项目内,新建一个 APP:
代码语言:javascript复制python manage.py startapp app_auth
修改配置
修改 UserBackend/UserBackend/settings.py 文件,将 app_auth 和 DRF 框架添加到应用列表,在 28 行附近:
代码语言:javascript复制ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app_auth',
'rest_framework',
'rest_framework.authtoken',
]
生成数据库
接着执行数据库迁移:
代码语言:javascript复制python manage.py makemigrations
python manage.py migrate
编写注册和登录视图
接下来,我们编写一个用户注册视图接口,让前端调用这个接口实现用户注册。
在 UserBackend/app_auth/views.py 文件中添加如下代码:
模块引入:
代码语言:javascript复制from django.contrib.auth.models import User
from rest_framework.authtoken.views import APIView,AuthTokenSerializer
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
用户注册:
代码语言:javascript复制# 用户注册
class Register(APIView):
def post(self,request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')
if User.objects.filter(username=username).exists():
resp = {
'status':False,
'data':'用户名已被注册'
}
else:
user = User.objects.create_user(username=username,password=password)
token, created = Token.objects.get_or_create(user=user)
resp = {
'status':True,
'token': token.key,
'user_id': user.pk,
'user_name': user.username,
}
return Response(resp)
用户登录:
代码语言:javascript复制# 用户登录
class Login(APIView):
def post(self, request, *args, **kwargs):
serializer = AuthTokenSerializer(data=request.data,context={'request': request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
return Response({
'status':True,
'token': token.key,
'user_id': user.pk,
'user_name':user.username,
})
设置路由
我们接着来配置一下上述两个接口视图的 URL 路由,在 UserBackend/UserBackend/urls.py 文件中修改为如下代码:
代码语言:javascript复制from django.urls import path
from app_auth import views
urlpatterns = [
path('api/register/',views.Register.as_view()),
path('api/login/',views.Login.as_view()),
]
测试接口
我们使用 postman 这个接口测试工具测试一下我们刚刚编写的两个接口。
注册成功:
用户名已被注册:
登录成功:
登录失败:
构建 Vue 前端页面
在完成后端接口的编写后,我们接着在构建前端页面。在这里,在这里,州的先生选择了 GitHub 上的一个 VUE 登录模板作为演示。
其仓库地址为:https://github.com/yuugou727/vue-simple-login-template
其项目结构如下所示:
首先下载源码:
代码语言:javascript复制git clone https://gitee.com/pear-admin/pear-admin-ant
然后安装依赖:
代码语言:javascript复制npm install
接着测试运行:
代码语言:javascript复制npm run dev
由于它的认证都是写死的,所以我们需要对其进行修改,使用我们编写的认证后端进行认证。
首先修改 src/components/Login.vue 文件,登录认证通过后端接口进行验证:
代码语言:javascript复制login(){
var that = this;
fetch('http://127.0.0.1:8000/api/login/',{
method:'POST',
headers: {
'Content-Type': 'application/json'
},
body:JSON.stringify({"username":this.userName,'password':this.password})
}).then(response => {
if(response.status == 200){
return response.json()
}else{
return Promise.reject('登录异常!')
}
}).then(
function(r){
console.log(r)
if(r.status){
localStorage.setItem('is_login', 'true')
localStorage.setItem('token', r.token)
localStorage.setItem('user_id', r.user_id)
localStorage.setItem('user_name', r.user_name)
that.$router.push('/');
}else{
alert("登录失败")
}
}
).catch(error => alert(error))
}
验证成功之后,我们这里把 token 等信息写到到 localstorage 中。当然,还可以使用 VueX 等工具来存储信息。
然后在 src/router.js 里面修改 router.beforeEach,用来限制未登录的访问:
代码语言:javascript复制router.beforeEach((to, from, next)=>{
const isLogin = localStorage.getItem('is_login') == 'true';
if( isLogin ){
if( to.path !== '/login' )
next();
else
next('/')
} else {
if( to.path !== '/login')
next('/login');
else
next();
}
});
我们来测试一下:
测试没问题了,我们将这个项目进行打包,运行如下命令:
代码语言:javascript复制npm run build
最终,我们会在 dist 文件夹下得到打包好的 js 文件。
实现 Django 内部署
VUE 项目打包好之后,我们可以通过 Nginx 之类的工具进行部署。
为了方便演示,我们将其直接通过 Django 的路由来进行访问。
首先我们在 UserBackend 文件夹下新建两个文件夹:static 和 template。
然后在 UserBackend/UserBackend/settings.py 文件第 62 行附近指定模板路径:
代码语言:javascript复制TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR,'template')
],
'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',
],
},
},
]
在 128 行附近添加:
代码语言:javascript复制if DEBUG:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]
else:
STATIC_ROOT = os.path.join(BASE_DIR,'static')
把 Vue 打包出来的 dist 目录复制到 static 文件夹内。
在 template 目录内新建一个 index.html,里面写入:
代码语言:javascript复制{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> 登录 </title>
</head>
<body>
<div id="app"></div>
<script src="{% static 'dist/build.js' %}"></script>
</body>
</html>
现在,我们就可以访问 127.0.0.1:8000 直接访问 vue 项目了:
最后
这里,我们用一个最基本的登录认证来演示 Django 后端接口与 Vue 前端项目的结合。虽然很简陋,但是也是麻雀虽小五脏俱全。
「天下大事做于细,天下难事作于易」,每一个复杂和系统,都是由无数个细小简单的构件组成。
希望本文能够给大家带来一丝灵感和思路。
最后需要 Django 和 Vue 完整源码的朋友,可以添加州的先生私人微信:taoist_ling,发送消息:django vue demo ,我将把源码打包发送给你。