本demo后端采用DRF框架(djangorestframeworf)框架,有对DRF不熟悉的可以先看看我之前的文章 分类 Django Restframework 下的文章
前端使用的是uni-app ,因为发现uni-app是在太好用了。就随便写了登录的例子
创建项目数据
安装DRF pip install djangorestframework
创建新项目并新建app为users
这里我们直接继承django自带的user模型
from django.db import models
from django.contrib.auth.models import AbstractUser
from shortuuidfield import ShortUUIDField
# Create your models here.
class UserProfile(AbstractUser):
uid = ShortUUIDField(primary_key=True, verbose_name='用户表主键')
openid = models.CharField(unique=True,max_length=200, blank=True, null=True, verbose_name='开放id')
telephone = models.CharField(unique=True, max_length=11, null=True, verbose_name="手机号码")
username = models.CharField(unique=True, max_length=20, null=True, verbose_name='用户名')
nickname = models.CharField(max_length=128, null=True, verbose_name='昵称')
avatar = models.CharField(max_length=200, verbose_name='头像链接', default='https://dmall.wouldmissyou.com/20200822112506.jpg')
gender = models.CharField(max_length=20, default='未知', verbose_name="性别")
province = models.CharField(max_length=128, verbose_name='所在地区', null=True)
address = models.CharField(max_length=128, verbose_name='详细地址', null=True)
is_active = models.BooleanField(default=True, verbose_name="是否可用")
is_staff = models.BooleanField(default=False, verbose_name="是否是员工")
date_joined = models.DateTimeField(auto_now_add=True, verbose_name='加入时间')
然后在setting.py文件制定我们的模型
#setting.py
AUTH_USER_MODEL = 'users.UserProfile'
然后进行数据迁移
序列化用户模型
在users app中,新建serializers.py文件进行模型序列化,我们要想前端返回我们的user数据,除了密码之外的我们都要返回,具体返回的内容还是看自己实际项目中的需求,我们就直接把密码排除点,其他的都返回
from rest_framework import serializers
from .models import UserProfile
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
exclude = ['password']
使用jwt进行认证
DRF中内置了好几种认证方法,但都不是我们所需要的,我们这里要使用JWT的方式进行认证,所以先安装一个包
pip install pyjwt
然后在users APP中新建一个py文件作为我们处理认证的文件,authentications.py
这个认证方式也是修改于DRF的内置方法BaseAuthentication,可以进源码看一下。
视图
关于微信认证的方式大家可以去看一下官方文档,这里就不阐述了
首先到微信小程序后台获取自己的appkey和appid
在setting.py中配置上
#setting.py
APP_ID = '填写你自己的小程序appid'
APP_KEY = '填写你自己的小程序appkey'
# 配置使用JWT方式认证
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ['users.authentications.JWTAuthentication']
}
然后在配置路由
path('login/', views.LoginView.as_view(), name='login'),
至此,后台部分配置完毕
前端部分
我这边为了后期方便开发,直接封装了一个简单的request.js
const baseURL = 'http://127.0.0.1:8000/';
const http = (options) => {
return new Promise((resolve, reject) => {
uni.showLoading({
title: '加载中...',
mask: options.load || false // 默认遮罩出现可以继续操作
});
try{
uni.request({
url: (options.baseURL || baseURL) + options.url,
method: options.method || 'POST', // 默认为POST请求
data: options.data, //请求超时在manifest.json配置
header: {
'token': uni.getStorageSync('token'),
'Content-Type': options.header == 'form' ? 'application/x-www-form-urlencoded' : 'application/json'
},
success: res => {
resolve(res.data)
},
fail: (err) => {
reject(err.data);
console.log(err);
uni.showToast({
title: '请检查网络连接',
icon: 'none'
})
/*错误码处理
let code = err.data.code;
switch (code) {
case 1000:
break;
default:
break;
} */
},
complete: () => {
uni.hideLoading();
}
});
}catch(e){
uni.hideLoading();
uni.showToast({
title: '服务端异常',
icon: 'none'
})
}
})
}
export default http
然后在main.js中声明一下
import http from "@/utils/http.js"
Vue.prototype.$HTTP = http
然后编写Login.vue
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<view>
<view>
<view class='header'>
<image :src='userInfo.avatar'></image>
<text>{{userInfo.nickname}}</text>
</view>
<view class='content'>
<view>申请获取以下权限</view>
<text>获得你的公开信息(昵称,头像、地区等)</text>
</view>
<button class='bottom' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo">
授权登录
</button>
<button class='bottom' type='warn' @click="logoutBtn">退出登录</button>
</view>
</view>
<!-- #endif -->
</view>
</template>
<script>
export default {
data() {
return {
userInfo: {},
isLogin: false //默认为true
};
},
mounted(){
const getuserInfo = uni.getStorageSync("userInfo")
this.userInfo = getuserInfo
},
methods: {
wxGetUserInfo() {
let _this = this;
uni.getUserInfo({
provider: 'weixin',
lang:"zh_CN",
success: function(infoRes) {
_this.data = infoRes.userInfo
// console.log(_this.data)
uni.showLoading({
title: "登录中"
})
uni.login({
provider: "weixin",
success: (loginres) => {
if (!loginres.code) {
console.log("登录失败,请再次点击~~");
return;
}
_this.data['code'] = loginres.code;
const params = _this.data
// console.log(params)
_this.$HTTP({
method: "POST",
url: "login/",
data: params
}).then((res) => {
console.log(res)
if (res.status=='202') {
uni.setStorageSync('token', 'JWT '+res.token)
uni.setStorageSync('userInfo', res.user)
_this.userInfo = uni.getStorageSync('userInfo')
}
})
}
})
}
})
},
logoutBtn(){
// 先判断用户是否登录
const userStatus = uni.getStorageSync('token')
if(!userStatus){
uni.showToast({
icon:"none",
title:"您未登录"
})
}else{
uni.removeStorageSync('token')
this.userInfo = {}
}
}
},
}
</script>
<style>
.header {
padding: 90rpx;
border-bottom: 1px solid #ccc;
text-align: center;
width: 100%;
line-height: 60rpx;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.header image {
width: 200rpx;
height: 200rpx;
}
.content {
margin-left: 50rpx;
margin-bottom: 90rpx;
}
.content text {
display: block;
color: #9d9d9d;
margin-top: 40rpx;
}
.bottom {
border-radius: 80rpx;
margin: 70rpx 50rpx;
font-size: 35rpx;
}
</style>
最后生成小程序看看效果吧
评论回复。。。。。