【Django开发】0到1美多商城项目md教程第7篇:登录,1. 互联开发者申请步骤【附代码文档】

美多商城完整教程(附代码资料)主要内容讲述:欢迎来到美多商城!,项目准备。展示用户注册页面,创建用户模块子应用。用户注册业务实现,用户注册前端逻辑。图形验证码,图形验证码接口设计和定义。短信验证码,避免频繁发送短信验证码。账号登录,用户名登录。登录,登录开发文档。用户基本信息,查询并渲染用户基本信息。收货地址,省市区三级联动。收货地址,展示地址前后端逻辑。商品数据库表设计,SPU和SKU。准备商品数据,容器化方案Docker。首页广告,展示首页商品频道分类。商品列表页,列表页面包屑导航。商品搜索,Haystack扩展建立索引。商品详情页,统计分类商品访问量。购物车管理,添加购物车。购物车管理,删除购物车。订单,结算订单。提交订单,使用乐观锁并发下单。对接系统,订单支付功能。页面静态化,首页广告页面静态化。MySQL读写分离,MySQL主从同步。

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~


全套教程部分目录:


部分文件图片:

登录

登录开发文档

登录:即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目。

1. 互联开发者申请步骤

若想实现登录,需要成为互联的开发者,审核通过才可实现。

  • 相关连接:[

2. 互联应用申请步骤

成为互联开发者后,还需创建应用,即获取本项目对应与互联的应用ID。

  • 相关连接:[

3. 网站对接登录步骤

互联提供有开发文档,帮助开发者实现登录。

  • 相关连接:[

4. 登录流程分析

5. 知识要点

  1. 当我们在对接第三方平台的接口时,一定要认真阅读第三方平台提供的文档。文档中一定会有接口的使用说明,方便我们开发。

定义登录模型类

登录成功后,我们需要将用户和美多商场用户关联到一起,方便下次登录时使用,所以我们选择使用MySQL数据库进行存储。

1. 定义模型类基类

为了给项目中模型类补充数据创建时间更新时间两个字段,我们需要定义模型类基类。 在meiduo_mall.utils/models.py文件中创建模型类基类。

from django.db import modelsclass BaseModel(models.Model):"""为模型类补充字段"""create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")class Meta:abstract = True  # 说明是抽象模型类, 用于继承使用,数据库迁移时不会创建BaseModel的表

2. 定义登录模型类

创建一个新的应用oauth,用来实现第三方认证登录。

# oauthurl(r'^oauth/', include('oauth.urls')),

oauth/models.py中定义身份(openid)与用户模型类User的关联关系

from django.db import modelsfrom meiduo_mall.utils.models import BaseModel# Create your models here.sclass OAuthUser(BaseModel):"""登录用户数据"""user = models.ForeignKey('users.User', on_delete=models.CASCADE, verbose_name='用户')openid = models.C harField(max_length=64, verbose_name='openid', db_index=True)class Meta:db_table = 'tb_oauth_qq'verbose_name = '登录用户数据'verbose_name_plural = verbose_name

3. 迁移登录模型类

$ python manage.py makemigrations
$ python manage.py migrate

登录工具LoginTool

1. LoginTool介绍

  • 该工具封装了登录时对接互联接口的请求操作。可用于快速实现登录。

2. LoginTool安装

pip install LoginTool

3. LoginTool使用说明

1.导入

from LoginTool.tool import OAuth

2.初始化OAuth对象

oauth = OAuth(client_id=settings._CLIENT_ID, client_secret=settings._CLIENT_SECRET, redirect_uri=settings._REDIRECT_URI, state=next)

3.获取登录扫码页面,扫码后得到Authorization Code

login_url = oauth.get_qq_url()

4.通过Authorization Code获取Access Token

access_token = oauth.get_access_token(code)

5.通过Access Token获取OpenID

openid = oauth.get_open_id(access_token)

OAuth2.0认证获取openid

待处理业务逻辑

# 提取code请求参数# 使用code向服务器请求access_token# 使用access_token向服务器请求openid# 使用openid查询该用户是否在美多商城中绑定过用户# 如果openid已绑定美多商城用户,直接生成JWT token,并返回# 如果openid没绑定美多商城用户,创建用户并绑定到openid

1. 获取登录扫码页面

1.请求方式

选项方案
请求方法GET
请求地址/qq/login/
>
2.请求参数:查询参数
参数名类型是否必传说明
nextstring用于记录登录成功后进入的网址
>
3.响应结果:JSON
字段说明
code状态码
errmsg错误信息
login_url登录扫码页面链接
>
4.后端逻辑实现
class AuthURLView(View):"""提供登录页面网址"""def get(self, request):# next表示从哪个页面进入到的登录页面,将来登录成功后,就自动回到那个页面next = request.GET.get('next')# 获取登录页面网址oauth = OAuth(client_id=settings._CLIENT_ID, client_secret=settings._CLIENT_SECRET, redirect_uri=settings._REDIRECT_URI, state=next)login_url = oauth.get_qq_url()return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url':login_url})

5.登录参数

_CLIENT_ID = '101518219'
_CLIENT_SECRET = '418d84ebdc7241efb79536886ae95224'
_REDIRECT_URI = '

2. 接收Authorization Code

提示:

  • 用户在登录成功后,会将用户重定向到我们配置的回调网址。
  • 在重定向到回调网址时,会传给我们一个Authorization Code
  • 我们需要拿到Authorization Code完成OAuth2.0认证获取openid
  • 在本项目中,我们申请登录开发资质时配置的回调网址为:

  • `

  • 互联重定向的完整网址为:

  • `

class AuthUserView(View):"""用户扫码登录的回调处理"""def get(self, request):"""Oauth2.0认证"""# 接收Authorization Codecode = request.GET.get('code')if not code:return http.HttpResponseForbidden('缺少code')pass
url(r'^oauth_callback/$', views.AuthUserView.as_view()),

3. OAuth2.0认证获取openid

  1. 使用code向服务器请求access_token
  2. 使用access_token向服务器请求openid
class AuthUserView(View):"""用户扫码登录的回调处理"""def get(self, request):"""Oauth2.0认证"""# 提取code请求参数code = request.GET.get('code')if not code:return http.HttpResponseForbidden('缺少code')# 创建工具对象oauth = OAuth(client_id=settings._CLIENT_ID, client_secret=settings._CLIENT_SECRET, redirect_uri=settings._REDIRECT_URI)try:# 使用code向服务器请求access_tokenaccess_token = oauth.get_access_token(code)# 使用access_token向服务器请求openidopenid = oauth.get_open_id(access_token)except Exception as e:logger.error(e)return http.HttpResponseServerError('OAuth2.0认证失败')pass

4. 本机绑定www.meiduo.site域名

1.ubuntu系统或者Mac系统

编辑 /etc/hosts

2.Windows系统

编辑 C:\Windows\System32\drivers\etc\hosts

openid是否绑定用户的处理

1. 判断openid是否绑定过用户

使用openid查询该用户是否在美多商城中绑定过用户。

try:oauth_user = OAuthUser.objects.get(openid=openid)
except OAuthUser.DoesNotExist:# 如果openid没绑定美多商城用户pass
else:# 如果openid已绑定美多商城用户pass

2. openid已绑定用户的处理

如果openid已绑定美多商城用户,直接生成状态保持信息,登录成功,并重定向到首页。

try:oauth_user = OAuthUser.objects.get(openid=openid)
except OAuthUser.DoesNotExist:# 如果openid没绑定美多商城用户pass
else:# 如果openid已绑定美多商城用户# 实现状态保持qq_user = oauth_user.userlogin(request, qq_user)# 响应结果next = request.GET.get('state')response = redirect(next)# 登录时用户名写入到cookie,有效期15天response.set_cookie('username', qq_user.username, max_age=3600 * 24 * 15)return response

3. openid未绑定用户的处理

  • 为了能够在后续的绑定用户操作中前端可以使用openid,在这里将openid签名后响应给前端。
  • openid属于用户的隐私信息,所以需要将openid签名处理,避免暴露。
try:oauth_user = OAuthUser.objects.get(openid=openid)
except OAuthUser.DoesNotExist:# 如果openid没绑定美多商城用户access_token = generate_eccess_token(openid)context = {'access_token': access_token}return render(request, 'oauth_callback.html', context)
else:# 如果openid已绑定美多商城用户# 实现状态保持qq_user = oauth_user.userlogin(request, qq_user)# 重定向到主页response = redirect(reverse('contents:index'))# 登录时用户名写入到cookie,有效期15天response.set_cookie('username', qq_user.username, max_age=3600 * 24 * 15)return response

oauth_callback.html中渲染access_token

<input v-model="access_token" type="hidden" name="access_token" value="{{ access_token }}">

4. 补充itsdangerous的使用

  • itsdangerous模块的参考资料链接 [
  • 安装:pip install itsdangerous

  • TimedJSONWebSignatureSerializer的使用

  • 使用TimedJSONWebSignatureSerializer可以生成带有有效期token

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from django.conf import settings# serializer = Serializer(秘钥, 有效期秒)serializer = Serializer(settings.SECRET_KEY, 300)# serializer.dumps(数据), 返回bytes类型token = serializer.dumps({'mobile': '18512345678'})
token = token.decode()# 检验token# 验证失败,会抛出itsdangerous.BadData异常serializer = Serializer(settings.SECRET_KEY, 300)
try:data = serializer.loads(token)
except BadData:return None

补充:openid签名处理

  • oauth.utils.py
def generate_eccess_token(openid):"""签名openid:param openid: 用户的openid:return: access_token"""serializer = Serializer(settings.SECRET_KEY, expires_in=constants.ACCESS_TOKEN_EXPIRES)data = {'openid': openid}token = serializer.dumps(data)return token.decode()

openid绑定用户实现

类似于用户注册的业务逻辑

  • 当用户输入的手机号对应的用户已存在

  • 直接将该已存在用户跟openid绑定

  • 当用户输入的手机号对应的用户不存在

  • 新建一个用户,并跟openid绑定

class AuthUserView(View):"""用户扫码登录的回调处理"""def get(self, request):"""Oauth2.0认证"""......def post(self, request):"""美多商城用户绑定到openid"""# 接收参数mobile = request.POST.get('mobile')pwd = request.POST.get('password')sms_code_client = request.POST.get('sms_code')access_token = request.POST.get('access_token')# 校验参数# 判断参数是否齐全if not all([mobile, pwd, sms_code_client]):return http.HttpResponseForbidden('缺少必传参数')# 判断手机号是否合法if not re.match(r'^1[3-9]\d{9}$', mobile):return http.HttpResponseForbidden('请输入正确的手机号码')# 判断密码是否合格if not re.match(r'^[0-9A-Za-z]{8,20}$', pwd):return http.HttpResponseForbidden('请输入8-20位的密码')# 判断短信验证码是否一致redis_conn = get_redis_connection('verify_code')sms_code_server = redis_conn.get('sms_%s' % mobile)if sms_code_server is None:return render(request, 'oauth_callback.html', {'sms_code_errmsg':'无效的短信验证码'})if sms_code_client != sms_code_server.decode():return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})# 判断openid是否有效:错误提示放在sms_code_errmsg位置openid = check_access_token(access_token)if not openid:return render(request, 'oauth_callback.html', {'openid_errmsg': '无效的openid'})# 保存注册数据try:user = User.objects.get(mobile=mobile)except User.DoesNotExist:# 用户不存在,新建用户user = User.objects.create_user(username=mobile, password=pwd, mobile=mobile)else:# 如果用户存在,检查用户密码if not user.check_password(pwd):return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'})# 将用户绑定openidtry:OAuthUser.objects.create(openid=openid, user=user)except DatabaseError:return render(request, 'oauth_callback.html', {'qq_login_errmsg': '登录失败'})# 实现状态保持login(request, user)# 响应绑定结果next = request.GET.get('state')response = redirect(next)# 登录时用户名写入到cookie,有效期15天response.set_cookie('username', user.username, max_age=3600 * 24 * 15)return response

用户中心

用户基本信息

用户基本信息逻辑分析

1. 用户基本信息逻辑分析

以下是要实现的后端逻辑

  1. 用户模型补充email_active字段
  2. 查询并渲染用户基本信息
  3. 添加邮箱
  4. 发送邮箱验证邮件
  5. 验证邮箱

    提示:

  6. 用户添加邮箱时,界面的局部刷新,我们选择使用Vue.js来实现。

未完待续, 同学们请等待下一期

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/308853.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第二十五天|216.组合总和III、17.电话号码的字母组合

216. 组合总和 III 思路&#xff1a; 本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。 相对于 77. 组合&#xff0c;无非就是多了一个限制&#xff0c;本题是要找到和为n的k个数的组合&#xff0c;而整个集合已经是固定的了[1,...,9]。 本题k相当于树的深…

vue列表列表过滤

对已知的列表进行数据过滤(根据输入框里面的内容进行数据过滤) 编写案例 通过案例来演示说明 效果就是这样的 输入框是模糊查询 想要实现功能&#xff0c;其实就两大步&#xff0c;1获取输入框内容 2根据输入内容进行数据过滤 绑定收集数据 我们可以使用v-model去双向绑定 …

Java 使用 ant.jar 执行 SQL 脚本文件

Java 使用 ant.jar 执行 SQL 脚本文件&#xff0c;很简单。 在 pom.xml 中导入 ant 依赖 <dependency><groupId>org.apache.ant</groupId><artifactId>ant</artifactId><version>1.10.11</version> </dependency>sql 脚本文件…

【2024】使用Rancher管理k8s集群和创建k8s集群

Rancher管理k8s集群及创建k8s集群。 Rancher版本为:2.8.2目录 rancher管理k8s集群rancher创建k8s集群rancher管理k8s集群 使用rancher管理已经存在的k8s集群。 本部分内容需要自行准备好k8s集群及rancher平台,部署请看本人其他文章 。 登录到rancher平台后,点击集群管理,…

c++修炼之路之vector模拟实现

目录 前言&#xff1a; 一&#xff1a;在STL的开源代码中的vector的实现 二&#xff1a;模拟实现 1.数据成员size()capacity() 2.resizereserve 3.构造函数析构函数赋值重载 4.迭代器[] 5.push_backinserterase迭代器失效问题 三&#xff1a;测试用例和全部代码 接下…

【LAMMPS学习】八、基础知识(1.8)键的断裂

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

【C++庖丁解牛】哈希表/散列表的设计原理 | 哈希函数

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1.哈希概念2.哈希冲突…

推荐七个Python效率工具!

为了提高效率&#xff0c;我们在平时工作中常会用到一些Python的效率工具&#xff0c;Python作为比较老的编程语言&#xff0c;它可以实现日常工作的各种自动化。为了更便利的开发项目&#xff0c;这里给大家推荐几个Python的效率工具。 1、Pandas-用于数据分析 Pandas是一个强…

复杂DP算法(动态规划)

复杂DP算法 一、线性DP例题1、鸣人的影分身题目信息思路题解 2、糖果题目信息思路题解 二、区间DP例题密码脱落题目信息思路题解 三、树状DP例题生命之树题目信息思路题解 一、线性DP 例题 1、鸣人的影分身 题目信息 思路 题解 #include <bits/stdc.h> #define endl …

ZISUOJ 数据结构-线性表

题目列表&#xff1a; 问题 A: 逆序链表建立 思路&#xff1a; 可以使用头插法插入所有元素后正序遍历输出或者使用尾插法逆序遍历&#xff0c;推荐使用双链表。这是链表系列的第一个题&#xff0c;那这个题下面的参考题解的各种解法我会尽可能写全一些。 参考题解1&#xff0…

【OTA】STM32-OTA升级——持续更新

【OTA】STM32-OTA升级——持续更新 文章目录 前言一、ymodem串口协议1、Ymodem 协议2、PC3、蓝牙4、WIFI云平台 二、UDS车载协议1.UDS协议 总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、ymodem串口协议 1、Ymodem 协议 STM32 Ymodem …

【I/O】基于事件驱动的 I/O 模型---Reactor

Reactor 模型 BIO 到 I/O 多路复用 为每个连接都创建一个线程 假设我们现在有一个服务器&#xff0c;想要对接多个客户端&#xff0c;那么最简单的方法就是服务端为每个连接都创建一个线程&#xff0c;处理完业务逻辑后&#xff0c;随着连接关闭线程也要销毁&#xff0c;但是…

每日一题(leetcode238):除自身以外数组的乘积--前缀和

不进阶是创建两个数组&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int nnums.size();vector<int> left(n);vector<int> right(n);int mul1;for(int i0;i<n;i){mul*nums[i];left[i]mul;}mul1;for…

前端开发攻略---根据音频节奏实时绘制不断变化的波形图。深入剖析如何通过代码实现音频数据的可视化。

1、演示 2、代码分析 逐行解析 JavaScript 代码块&#xff1a; const audioEle document.querySelector(audio) const cvs document.querySelector(canvas) const ctx cvs.getContext(2d)这几行代码首先获取了 <audio> 和 <canvas> 元素的引用&#xff0c;并使用…

Java编程练习之抽象类与抽象方法

使用抽象类和抽象方法时&#xff0c;需要遵循以下原则&#xff1a; 1&#xff09;在抽象类中&#xff0c;可以包含抽象方法&#xff0c;也可以不包含抽象方法&#xff0c;但是包含了抽象方法的类必须被定义为抽象类&#xff1b; 2&#xff09;抽象类不能直接被实例化&#xf…

BugKu:Flask_FileUpload

Flask_FileUpload 解题思路 查看源码&#xff1a; 编写上传的文件 获得结果 小结 文件上传漏洞&#xff1a; 文件上传漏洞是指用户上传了一个可执行的脚本文件&#xff0c;并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的&#xff0c;“文件上…

探索ERC20代币:构建您的第一个去中心化应用

下面文章中会涉及到该资源中的代码&#xff0c;如果想要完整版代码可以私信我获取&#x1f339; 文章目录 概要整体架构流程技术名词解释ERC20智能合约web3.js 技术细节ERC20合约部署创建前端界面前端与智能合约互连运行DAPP 小结 概要 在加密货币世界中&#xff0c;ERC20代币…

poi-tl的使用(通俗易懂,全面,内含动态表格实现 包会!!)

最近在做项目时候有一个关于解析Html文件&#xff0c;然后将解析的数据转化成word的需求&#xff0c;经过调研&#xff0c;使用poi-tl来实现这个需求&#xff0c;自己学习花费了一些时间&#xff0c;现在将这期间的经验总结起来&#xff0c;让大家可以快速入门 poi-tl的介绍 …

大数据产品有哪些分类?各类里知名大数据产品都有哪些?

随着互联网技术的持续进步和全球数字化转型的推进&#xff0c;我们正处于一个数据爆炸的时代。在这样的大背景下&#xff0c;大数据已经逐渐崭露头角&#xff0c;成为了推动各行各业发展的关键因素和核心资源。大数据不仅仅是指数据的规模巨大&#xff0c;更重要的是它蕴含的价…

Python八股文:基础知识Part2

1. Python中变量的保存和访问 Python中的变量实际上是一个指向对象的引用&#xff0c;每个对象都有一个唯一的标识符&#xff08;即内存地址&#xff09;。对于一些不可变对象&#xff0c;如字符串和整数&#xff0c;因为它们的值不可更改&#xff0c;所以当多个变量引用相同的…