2019-08-11 Django+Vue.js实现前后端分离的单页面博客系统(4)数据库的设置与登录、登出、权限控制功能的实现

数据库的配置

现在终于可以进入后端的开发了。不过在开发其他功能之前,首先还是要配置好数据库。

数据库方面,我使用的是自带的SQLite数据库,因为使用起来比较方便,而且也有与之对应的自带的数据库管理系统。

因为只有两张表,所以models.py中只有两个类:

models.py(未完成?)

from django.db import models
import time

# Create your models here.

# 用户,其实只有博主一个人
class User(models.Model):
    username = models.CharField(max_length=150)
    password = models.CharField(max_length=150)

# 文章,有标题、内容和发表时间三个属性
class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.CharField(max_length=5000)
    date = models.DateTimeField('date', default=time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))

编写完成后创建管理员用户:

python manage.py createsuperuser

然后执行迁移命令,初始化数据库:

python manage.py makemigrations backend
python manage.py sqlmigrate backend 0001
python manage.py migrate

因为用户只有博主一个,所以使用命令行来创建博主用户。

>>> from backend.models import User
>>> u = User(username="admin", password="admin123456")
>>> u.save()

将User类和Article类都加入admin.py中,这样才能在管理页面中看到这两项:

from django.contrib import admin
from .models import User, Article

# Register your models here.

admin.site.register(User)
admin.site.register(Article)

执行python manage.py runserver之后进入127.0.0.1:8000/admin,就可以看到后台管理页面了。

登录功能的实现

接下来首先要实现登录功能,才能继续开发其他功能,毕竟很多功能的实现都需要基于权限控制。

与PHP留言板项目不同,这次使用Cookie来做会话控制。

登录的流程是这样的:前端发起Ajax请求,将用户名和密码发给后端,后端经过校验之后返回一个“状态码”和与之对应的消息给前端,并且设置Cookie,前端根据接收到的状态码做相应处理。

Django在查找数据库这方面还是非常简单的,有对应的API,并不需要编写SQL语句。

后端

views.py(未完成)

from django.shortcuts import render
from django.views.generic import View
from django.http import HttpResponseRedirect, JsonResponse, HttpResponse
from .models import User


# Create your views here.


class Login(View):
    def get(self, request):
        return HttpResponseRedirect('/login')

    def post(self, request):
        print(request)
        name = request.POST.get('name', None)
        pwd = request.POST.get('password', None)
        try:
            user = User.objects.get(username=name)

            if user.password == pwd:
                r = {
                    'status': 0,
                    'msg': '登录成功!'
                }
                response = JsonResponse(r)
                response.set_cookie('username', name, expires=60 * 15)
                return response
            else:
                r = {
                    'status': 1,
                    'msg': '密码错误!'
                }
                response = JsonResponse(r)
                return response

        except Exception as e:
            r = {
                'status': 2,
                'msg': '你不是管理员!'
            }

        print('username:' + name)
        print('password:' + pwd)
        print(r)
        return JsonResponse(r)

有部分代码只是测试用的,完成之后会删掉。

前端

Login.vue(未完成?)

<!--
  登录组件
  TODO:开发登录功能
-->
<template>
  <div class="container">
    <h1 class="display-3">Login</h1>
    <hr class="my-1">
    <form id="login-form">
      <div class="form-group">
        <label for="name" class="text-left">Username:</label>
        <input type="text" class="form-control" id="name" placeholder="Username" v-model="name">
      </div>
      <div class="form-group">
        <label for="password">Password:</label>
        <input type="password" class="form-control" id="password" placeholder="Password" v-model="password">
      </div>
      <input type="button" @click="post" class="btn btn-secondary" value="Submit">
    </form>
  </div>
</template>

<script>
  export default {
    name: 'Login',
    data () {
      return {
        name: '',
        password: ''
      }
    },
    mounted () {
      let allCookies = document.cookie
      if (allCookies.indexOf('username') !== -1) {
        this.$router.push('/manage')
      }
    },
    methods: {
      post () {
        let data = new URLSearchParams()
        data.append('name', this.name)
        data.append('password', this.password)
        this.axios
          .post('/login/check/', data)
          .then(function (response) {
            console.log(response)
            alert(response.data.msg)
            if (response.data.status === 0) {
              location.href = '/manage'
            }
          })
          .catch(function (error) {
            console.log(error)
          })
      }
    }
  }
</script>

<style scoped>
  .container {
    padding-top: 100px;
  }

  h1 {
    padding-bottom: 20px;
  }

  form {
    margin-top: 30px;
  }
</style>

这里在mounted()函数中做了一个判断:如果已经有cookie了,那就不需要登录,直接进入管理页面。其他组件中也会用到这种判断。

这里用location.href来跳转也是无奈之举,因为使用vue-router总是出各种各样的问题,无奈之下只好换这个了。

登出功能的实现

这次的登出功能非常简单,因为只是销毁Cookie,所以都不用麻烦后端,直接使用JavaScript来销毁就可以。销毁的原理是使Cookie超出有效期。

借鉴了百度经验上的一些代码,侵删。

Logout.vue(未完成?)

<!--
  登出组件
  TODO: 开发登出功能
-->
<template>
    
</template>

<script>
  export default {
    name: 'Logout',
    methods: {
    },
    mounted () {
      let oDate=new Date()
      oDate.setDate(oDate.getDate() + -1);
      document.cookie = 'username' + '=' + 'admin'+';expires='+oDate;
      alert('登出成功')
      this.$router.push('/')
    }
  }
</script>

<style scoped>

</style>

权限控制的实现

因为是使用Cookie进行会话控制,所以权限控制也是根据判断有无Cookie来完成。只要用一点JavaScript就可以,并不是很难。

核心代码如下:

mounted () {
      let allCookies = document.cookie
      if (allCookies.indexOf('username') === -1) {
        this.$router.push('/login')
      }

也就是在组件装载的时候使用JavaScript判断Cookie是否存在,如果不存在,就使用vue-router进行强制跳转。在需要权限控制的组件里加上这段代码,然后稍微改一改变量和跳转的目标URL就可以了。

推荐阅读更多精彩内容