登录到主页功能实现

1创建新项目的准备工作

1.1命令框内创建新项目

打开指定文件夹,在路径位置输入cmd打开命令行
django-admin startproject 项目名 创建项目

1.2在新项目内创建子应用

python manage.py startapp 子应用名

1.3在settings.py文件内注册

在settings.py文件内注册子应用
跨域也顺便弄好
认证模型类也弄好
DRF工程
下载第三方模块
在黑窗口内进行安装
pip install djangorestframework

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
	'corsheaders',  #配置跨域
    'rest_framework',   #配置drf框架
    '创建的子应用名'    #注册子应用
]
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'corsheaders.middleware.CorsMiddleware'   # 添加跨域中间件
]
CORS_ORIGIN_WHITELIST=[
    'http://127.0.0.1:8080',
    'http://localhost:8080'
]
CORS_ALLOW_CREDENTIALS=True
CORS_ALLOW_METHODS=('*')
CORS_ALLOW_HEADERS=('*')
#用户认证模型类
AUTH_USER_MODEL='子应用名.模型类名'

1.5配置数据库

在settings.py文件内

# 配置数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 使用mysql数据库
        'HOST': 'localhost',  # 主机
        'PORT': 3306,  		# 端口
        'USER': 'root',  	# 数据库的用户名
        'PASSWORD': '密码', # 数据库的密码
        'NAME': '创建的数据库名',  	# 数据库的名字
    }
}

1.6修改语言和时区

在settings.py文件内

LANGUAGE_CODE = 'zh-Hans'  #语言

TIME_ZONE = 'Asia/Shanghai'  #时区

1.7安装数据库

在跟项目名同名的文件夹内init.py文件里安装

import pymysql
pymysql.install_as_MySQLdb()

1.8创建模型类

在子应用文件夹里的models.py创建

from django.db import models
# Create your models here.
#user
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
class User(AbstractUser):
    mobile=models.CharField('手机号',max_length=11)
    last_login = models.DateTimeField('上次登录时间',default=timezone.now)
    def __str__(self):
        return self.username
    class Meta:
        db_table='user'

1.9创建好模型类后进行迁移

在项目内终端执行
生成迁移文件:python manage.py makemigrations
执行迁移:python manage.py migrate
如果迁移出错,把数据库删了创建新的数据库,生成的迁移文件也删了,重新执行上面2个步骤

认证模型类

在settings.py文件内注册

#用户认证模型类
AUTH_USER_MODEL='users.User'

登录后端接口 实现

登录接口
api: /users/logincount/
method: POST
data:
{
username: this.username,
password: this.password,
mobile: this.phone,
code: this.smscode
}
 
响应:
code == “204” 验证码过期或者错误
code == “205” 用户名或密码错误
code == “206” 没有管理员权限
code == “207” 密码已重置
code == “200” 登录成功, 进入首页
code == “201” 注册成功,需申请管理员权限 后台superuser
必须是管理员才可以登录,即is_staff=True & is_active=True;这些可以使用superuser在后台修改!!!

登录的逻辑:

  1. 用户第一次登录,使用手机验证码进行注册
    存储用户名、密码、手机号,返回201
  2. 用户第 二 次及 n 次登录,优先使用密码验证;
    用户名、密码均正确,检查用户是否有管理员权限(只有is_staff=True&is_active=True时,才允许登录),分别返回响应;
  3. 用户、密码验证未通过时,检查是否有短信验证码,有则验证短信验证码(验证通过则重置密码,返回207);
    无短信验证码,直接返回205

编写视图

from rest_framework.views import APIView
from rest_framework.response import Response
from users.models import User
import random,redis
#登录的视图LoginAPIView
from django.contrib.auth.hashers import check_password
from datetime import datetime
from rest_framework_jwt.utils import jwt_encode_handler,jwt_payload_handler
class LoginAPIView(APIView):
    def post(self,request):
        #1.获取前段数据
        username=request.data.get('username')
        password=request.data.get('password')
        mobile=request.data.get('mobile')
        smsCode=request.data.get('smsCode')
        #2.判断是不是新用户,
        user=User.objects.filter(username=username).first()
        redis_conn=redis.Redis(host='127.0.0.1',port=6379,password='shayebushi')
        if user:
            #该用户是第二次或第n次登录,优先使用密码认证,密码错误再考虑短信
            if check_password(password,user.password):
                #密码正确,判断密码是否是管理员
                if user.is_staff and user.is_active:
                    #允许成功登录
                    token=self.gen_token(user)
                    user.last_login=datetime.now()
                    user.save()
                    return Response({
                        'code':200,
                        'msg':'登陆成功,进入首页',
                        'data':{
                            'uid': user.id,
                            'username': user.username,
                            'token': token
                        }
                    })
                else:
                    return Response({
                        'code':206,
                        'msg':'没有管理员权限'
                    })

            else:
                #密码不正确,考虑有没有短信验证码,若有smsCode属于密码重置
                if smsCode:
                    #前端传入短信验证码,密码重置
                    validation=self.validate_sms_code(smsCode,mobile,redis_conn)
                    if validation:
                        #完成短信认证,开始重写密码
                        user.set_password(password)
                        user.save()
                        return Response({
                            'code':207,
                            'msg':'密码已重置'
                        })
                    else:
                        return Response({
                            'code':204,
                            'msg':'验证码已过期或错误'
                        })
                else:
                    return Response({
                        'code':205,
                        'msg':'用户名或密码错误'
                    })
        else:
            #用户第一次来注册,需要使用短信验证码来认证
            if smsCode:
                #使用验证码验证 并注册
                validation=self.validate_sms_code(smsCode,mobile,redis_conn)
                if validation:
                    #注册用户信息
                    User.objects.create_user(username=username,password=password,mobile=mobile)
                    return Response({
                        'code':201,
                        'msg':'注册成功需要申请管理员权限'
                    })
                else:
                    return Response({
                        'code':204,
                        'msg':'验证码过期或错误'
                    })
            else:
                return Response({
                    'code':208,
                    'msg':'第一次登录需使用收集验证码'
                })
    @staticmethod
    def gen_token(user):
        '''
        :param user:  用户对象
        :return:    jwt token 字符串
        '''
        #生成payload载荷信息
        payload=jwt_payload_handler(user)
        # 生成token
        token=jwt_encode_handler(payload)
        return token

    @staticmethod
    def validate_sms_code(smsCode,mobile,redis_sonn):
        '''
        :param smsCode:  短信验证码 字符串
        :param mobile:  手机号 字符串
        :param redis_sonn:  redis 链接对象
        :return:   Boolean
        '''
        #构造key
        key='sms_%s'%mobile
        #获取redis中的验证码
        stored_code=redis_sonn.get(key)
        #开始对比
        if stored_code and stored_code.decode()==smsCode:
            return True
        else:
            return False

配置路由

from django.urls import path
from users import views
urlpatterns = [
    #获取短信验证码
    path('sms_code/',views.SmsCodeAPIView.as_view()),
    # 用户的登录
    path('logincount/',views.LoginAPIView.as_view())
]

登录用户信息 前端页面实现

<script>
import cons from "@/components/constant";
export default {
  name: "Login",
  data() {
    return {
      errshow: false,
      errmsg: "",
      password: "",
      username: "",
      phone: "",
      smsCode: "",
    };
  },
  methods: {
    // 获取短信验证码
    getSmsCode() {
      if (!this.phone){
        this.$message({
          type:'warning',
          message:'手机号不能为空'
        })
        return
      }
      // 一般要加正则匹配
      // 发送短信获取验证码
      this.axios.get('/v1/users/sms_code/',{
        params:{
          mobile:this.phone
        }
      }).then((result) => {
        if (result.data.code==200){
          this.$message({
            type:'success',
            message:result.data.msg
          })
        }else{
          this.$message({
            type:'error',
            message:result.data.msg
          })
        }
      }).catch((err) => {
        console.log('获取短信验证码错误',err)
      });
    },
    // 登录
    fnLogin() {
      if (this.username == "" || this.password == "") {
        this.errmsg = "用户名或密码不能为空";
        this.errshow = true;
        return;
      }
      //http://www.meiduo.site:8000/meiduo_admin/authorizations/
      
      // 发送请求
      this.axios.post('/v1/users/logincount/',{
        username:this.username,
        password:this.password,
        mobile:this.phone,
        smsCode:this.smsCode
      }).then((result) => {
        console.log('登录的响应:',result)
        // 处理响应
        if (result.data.code==200){
          this.$message({
            type:"success",
            message:result.data.msg
          })
          // 保存 useranme uid token 
          localStorage.clear()
          localStorage.token=result.data.data.token
          localStorage.uid=result.data.data.uid
          localStorage.username=result.data.data.username
          // 进入项目的首页
          this.$router.push({path:'/home'})
        }else{
          this.errshow=true
          this.errmsg=result.data.msg
        }
      }).catch((err) => {
        console.log('登录错误:',err)
      });
    },
  },
};
</script>

axios注意事项

如果请求错误,就去main.js里查看axios是否配置
在这里插入图片描述

统计用户总数,日增,日活跃数

后端

需要导包 import time
利用查询,获取相关的数据

#统计用户总数的视图
class TotaCountAPIView(APIView):
    def get(self,request):
        #统计用户总数
        total_count=User.objects.all().count()
        return Response({
            'code':200,
            'total_count':total_count
        })
#日增用户的视图
class DayIncrementAPIView(APIView):
    def get(self,request):
        # 统计日增用户    #需要导包 import time
        current_data=time.strftime('%Y-%m-%d')       #查询同一天注册的用户
        day_increment=User.objects.filter(date_joined__contains=current_data).count()
        return Response({
            'code':200,
            'day_increment':day_increment
        })
#统计日活跃用户 视图
class DayLiveAPIView(APIView):
    def get(self,request):
    	# 统计日活跃用户		#需要导包 import time
        current_data = time.strftime('%Y-%m-%d')
        day_live = User.objects.filter(last_login__contains=current_data).count()
        return Response({
            'code': 200,
            'day_live': day_live
        })

配置路由

from django.urls import path
from users import views
urlpatterns = [
    #获取短信验证码
    path('sms_code/',views.SmsCodeAPIView.as_view()),
    # 用户的登录
    path('logincount/',views.LoginAPIView.as_view()),
    #统计用户总数
    path('total_count/',views.TotaCountAPIView.as_view()),
    #获取日增用户
    path('day_increment/',views.DayIncrementAPIView.as_view()),
    #获取日活用户
    path('day_live/',views.DayLiveAPIView.as_view()),
]

前端

注意,要找到对应的vue组件,
例如:CountPannel.vue
在组件内需要修改的地方进行修改

<script>
export default {
  name: 'CountPannel',
  data(){
    return {
      total_count:0,
      day_increment:0,
      day_active:0,
      day_orders:0
    }
  },
  mounted(){
    let token = localStorage.token;

    // 获取总人数
    this.axios.get('/v1/users/total_count/', {
        headers: {
          'Authorization': 'JWT ' + token
        },
        responseType: 'json',
    })
    .then(res=>{
        console.log('统计用户总数的响应',res);
        // {code:200,total_count:300}
        this.total_count = res.data.total_count;

    }).catch(err=>{
       console.log(err.response);      
       if(err.response.status==401){
          this.$router.push({path:'/'});
       }
    });

    // 获取日增人数
    this.axios.get('/v1/users/day_increment/', {
        headers: {
          'Authorization': 'JWT ' + token
        },
        responseType: 'json',
    })
    .then(res=>{
      console.log('获取日增用户的响应',res)
        this.day_increment = res.data.day_increment;
    }).catch(err=>{
       console.log(err);
    });

    // 获取日活人数
    this.axios.get('/v1/users/day_live/', {
        headers: {
          'Authorization': 'JWT ' + token
        },
        responseType: 'json',
    })
    .then(res=>{
      console.log('获取日活的用户',res)
        this.day_active = res.data.day_live;
    }).catch(err=>{
       console.log(err);
    });
}
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值