Django + Vue 快速实现前后端分离的用户认证

2021-07-20 11:46:29 浏览数 (1)

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 ,我将把源码打包发送给你。

0 人点赞