(根据居然老师直播课内容整理)

  • QQ登录:即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目。
  • 一般QQ登录成功就直接进入系统,本项目还需要绑定用户
  • 如果用户已注册,直接绑定用户
  • 如果没有注册,还需要分配用户信息

一、QQ登录开发文档

1、QQ互联开发者申请步骤

若想实现QQ登录,需要成为QQ互联的开发者,审核通过才可实现。
相关连接:http://wiki.connect.qq.com/%E6%88%90%E4%B8%BA%E5%BC%80%E5%8F%91%E8%80%85

2、QQ互联应用申请步骤

成为QQ互联开发者后,还需创建应用,即获取本项目对应与QQ互联的应用ID。
相关连接:http://wiki.connect.qq.com/__trashed-2

3、网站对接QQ登录步骤

QQ互联提供有开发文档,帮助开发者实现QQ登录。
相关连接:http://wiki.connect.qq.com/%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C_oauth2-0

  • QQ登录开发流程:(以下内容截取了2021.2.12QQ说明文档)

3.1 准备工作_OAuth2.0

  • 本步骤的作用:
    接入QQ登录前,网站需首先进行申请,获得对应的appid与appkey,以保证后续流程中可正确对网站与用户进行验证与授权。
  • 本步骤在整个流程中的位置:

3.1.1 申请appid和appkey

  • 申请appid和appkey的用途

    • appid:应用的唯一标识。在OAuth2.0认证过程中,appid的值即为oauth_consumer_key的值。
    • appkey:appid对应的密钥,访问用户资源时用来验证应用的合法性。在OAuth2.0认证过程中,appkey的值即为oauth_consumer_secret的值。
  • 申请地址
    https://connect.qq.com/manage.html#/

  • 申请流程

    • 1.开发者资质审核

      • 参考文章:开发者注册流程
    • 2.申请appid(oauth_consumer_key/client_id)和appkey(auth_consumer_secret/client_secret);
      • (1)进入https://connect.qq.com/manage.html#/页面,点击“创建应用”,在弹出的对话框中填写网站或应用的详细资料(名称,域名,回调地址);
      • (2)点击“确定”按钮,提交资料后,获取appid和appkey。
      • 注意:申请appid时,登录的QQ号码将与申请到的appid绑定,后续维护均需要使用该号码。
      • 注意:对appid和appkey信息进行保密,不要随意泄漏。

3.1.2 保证连接畅通

  • 接入QQ登录时,网站需要不停的和Qzone进行交互,发送请求和接受响应。

    • 1.对于PC网站:

      • 请在你的服务器上ping graph.qq.com ,保证连接畅通。
    • 2.移动应用无需此步骤

3.2 放置“QQ登录”按钮_OAuth2.0

  • 本步骤的作用:
    在网站页面上放置“QQ登录”按钮,并为按钮添加前台代码,实现点击按钮即弹出QQ登录对话框。
  • 本步骤在整个流程中的位置:

3.2.1 下载“QQ登录”按钮图片,并将按钮放置在页面合适的位置

  • 按钮图片下载: 点击这里下载 。
  • 按照UI规范,将按钮放置在页面合适的位置:点击这里查看。

3.2.2 为“QQ登录”按钮添加前台代码

  • 1.效果演示

    • 用户在页面上点击“QQ登录”按钮,将触发QQ登录对话框,效果如下图所示:
  • 2.前台代码
    • 为了实现上述效果,应该为“QQ登录”按钮图片添加如下前台代码:
<img src=QQ登录图标文件在服务器上的地址 onclick=按钮点击事件>
  • 3.代码示例

    • 写一个函数“toLogin()”,该函数通过调用“index.php”中的qq_login函数来实现将页面跳转到QQ登录页面。
      (示例中的oauth/index.php,请参见从SDK下载页面下载PHP SDK,在Connect2.1文件夹下的index.php文件。)
<script>function toLogin(){//以下为按钮点击事件的逻辑。注意这里要重新打开窗口//否则后面跳转到QQ登录,授权页面时会直接缩小当前浏览器的窗口,而不是打开新窗口var A=window.open("oauth/index.php","TencentLogin","width=450,height=320,menubar=0,scrollbars=1,resizable=1,status=1,titlebar=0,toolbar=0,location=1");}
</script>
  • 为按钮添加“toLogin()”事件:
 <a href="#" onclick='toLogin()'><img src="img/qq_login.png"></a>

3.3 使用Authorization_Code获取Access_Token

  • 本步骤的作用:
    通过用户验证登录和授权,获取Access Token,为下一步获取用户的OpenID做准备;
    同时,Access Token是应用在调用OpenAPI访问和修改用户数据时必须传入的参数。
    移动端应用可以直接获得AccessToken,请参考使用Implicit_Grant方式获取Access_Token
  • 本步骤在整个流程中的位置:
  • 对于应用而言,需要进行两步:
    • 1.获取Authorization Code;
    • 2.通过Authorization Code获取Access Token
  • 过程详解

Step1:获取Authorization Code(提供扫码页面)

  • 请求地址:PC网站:https://graph.qq.com/oauth2.0/authorize
  • 请求方法:GET
  • 请求参数:请求参数请包含如下内容:
参数 是否必须 含义
response_type 必须 授权类型,此值固定为“code”。
client_id 必须 申请QQ登录成功后,分配给应用的appid。
redirect_uri 必须 成功授权后的回调地址,必须是注册appid时填写的主域名下的地址,建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。
state 必须 client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。

返回说明:

  1. 如果用户成功登录并授权,则会跳转到指定的回调地址,并在redirect_uri地址后带上Authorization Code和原始的state值。如:
    PC网站:http://graph.qq.com/demo/index.jsp?code=9A5F************************06AF&state=test
    注意:此code会在10分钟内过期。
  2. 如果用户在登录授权过程中取消登录流程,对于PC网站,登录页面直接关闭;
    错误码说明:
    接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。
    PC网站接入时,错误码详细信息请参见:100000-100031:PC网站接入时的公共返回码。

Step2:通过Authorization Code获取Access Token

  • 请求地址:PC网站:https://graph.qq.com/oauth2.0/token

  • 请求方法:GET

  • 请求参数:请求参数请包含如下内容:

  • 返回说明:

    • 如果成功返回,即可在返回包中获取到Access Token。 如(不指定fmt时):

    • access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14

  • 错误码说明:
    接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。
    PC网站接入时,错误码详细信息请参见:100000-100031:PC网站接入时的公共返回码。

Step3:(可选)权限自动续期,获取Access Token

  • Access_Token的有效期默认是3个月,过期后需要用户重新授权才能获得新的Access_Token。本步骤可以实现授权自动续期,避免要求用户再次授权的操作,提升用户体验。
  • 请求地址:PC网站:https://graph.qq.com/oauth2.0/token
  • 请求方法:GET
  • 请求参数:请求参数请包含如下内容:
  • 返回说明:
    如果成功返回,即可在返回包中获取到Access Token。 如(不指定fmt时):
    access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14。
  • 错误码说明:
    接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。
    PC网站接入时,错误码详细信息请参见:100000-100031:PC网站接入时的公共返回码。

3.4 获取用户OpenID_OAuth2.0

  • 本步骤的作用:
    通过输入在上一步获取的Access Token,得到对应用户身份的OpenID。
    OpenID是此网站上或应用中唯一对应用户身份的标识,网站或应用可将此ID进行存储,便于用户下次登录时辨识其身份,或将其与用户在网站上或应用中的原有账号进行绑定。
  • 本步骤在整个流程中的位置:
  • 1 请求地址:PC网站:https://graph.qq.com/oauth2.0/me
  • 2 请求方法:GET
  • 3 请求参数:请求参数请包含如下内容:
参数 是否必须 含义
access_token 必须 在Step1中获取到的access token。
  • 4 返回说明
    PC网站接入时,获取到用户OpenID,返回包如下(如果fmt参数未指定):
callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} );

openid是此网站上唯一对应用户身份的标识,网站可将此ID进行存储便于用户下次登录时辨识其身份,或将其与用户在网站上的原有账号进行绑定。

  • 5 错误码说明
    接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。
    PC网站接入时,错误码详细信息请参见:100000-100031:PC网站接入时的公共返回码。

4、QQ登录流程分析

二、QQ登录工具QQLoginTool

  • 上面的登录流程可以使用QQLoginTool实现
  • 该工具封装了QQ登录时对接QQ互联接口的请求操作。可用于快速实现QQ登录。
  • QQLoginTool安装:pip install QQLoginTool
  • 使用说明
    • 1.导入
from QQLoginTool.QQtool import OAuthQQ
  • 2.初始化OAuthQQ对象
oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next)
  • 3.获取QQ登录扫码页面,扫码后得到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)

三、定义QQ登录模型类

  • QQ登录成功后,我们需要将QQ用户和商场用户关联到一起,方便下次QQ登录时使用,所以我们选择使用MySQL数据库进行存储。
  • 保存字段主要有:创建时间、更新时间 、QQ的openid和用户id
  • 此功能可以不创建新的app,直接在uses的modles.py里创建,也可以创建新的app,本次项目就创建新的app,方便以后写微信、支付宝等其它第三方登录
python ../manage.py startapp oauth

1、创建数据模型基类

  • 创建时间、更新时间这两个字段在很多表中都需要,固需要创建成基类,其它数据模型在其基础上继承
  • 此两字段不需要单独创建表,故定义为抽象模型类 abstract = True,数据库迁移时不创建新表
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:# 数据库迁移的时候不创建BaseModel这个表abstract = True

2、定义QQ登录模型类

  • 继承BaseModel类,用户id是外健,users.User类
from django.db import models
from utils.models import BaseModelclass OAuthQQUser(BaseModel):"""QQ登录用户数据"""user = models.ForeignKey('users.User', on_delete=models.CASCADE, verbose_name='用户')openid = models.CharField(max_length=64, verbose_name='openid')class Meta:db_table = 'tb_oauth_qq'verbose_name = 'QQ登录用户数据'verbose_name_plural = verbose_name

3、注册应用

4、数据库迁移

python manage.py makemigrations
python manage.py migrate

四、OAuth2.0认证获取openid

  • 首先前端发起QQ登录请求,需要后端返回一个QQ登录界面的链接
  • 前端接收到QQ登录界面的链接后,打开并展示QQ登录界面(由QQ服务器返回QQ登录界面及相关参数)
  • 用户扫描QQ登录链,完成QQ录登验证(QQ服务器处理)
  • 如果验证成功,QQ服务器会将处理结果回调信息传给后端,后端根据接口参数完成系统登录处理

1、获取QQ登录扫码页面

1.1 接口设计

  • 用户点击QQ登录图标,前端即会发起QQ登录的ajax请求
  • 后端接收到请求,接收参数,
  • 利用QQLoginTools工具得到QQ登录的url
  • 返回用JSON方式,发送给前端

1.1.1 请求方式

选项 方案
请求方法 GET
请求地址 /qq/login/

1.1.2 请求参数:查询参数

参数名 类型 是否必传 说明
next string 用于记录QQ登录成功后进入的网址

1.1.3 响应结果:JSON

字段 说明
code 状态码
errmsg 错误信息
login_url QQ登录扫码页面链接

1.2 QQ登录参数

  • QQ互联开发者申请后,会有以下3个参数:QQ_CLIENT_ID、QQ_CLIENT_SECRET、QQ_REDIRECT_URI
  • 一般公司会有专人负责申请,直接向公司领用此3个参数即可
  • 建议将此参数定义在配置文件中

1.3 后端逻辑实现

# ./apps/oauth/views.py
from django.shortcuts import render
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django import http
from utils.response_code import RETCODE# Create your views here.class QQAuthURLView(View):def get(self,request):# 获取参数next=request.GET.get("next")print(next)# 创建工具对象oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,redirect_uri=settings.QQ_REDIRECT_URI, state=next)# 生成扫描链接地址login_url = oauth.get_qq_url()return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})

1.3.2 注册路由

#  注册子路由
# ./apps/oauth/urls.py
from django.urls import path
from . import viewsurlpatterns = [# 提供QQ登录扫描页面path('qq/login/', views.QQAuthURLView.as_view()),]# 注册主路由
# ./lgshop/urls.py
from django.contrib import admin
from django.urls import path,includeurlpatterns = [path('admin/', admin.site.urls),path('users/', include('users.urls')),path('', include('contents.urls')),path('',include("verifications.urls")),path("",include("oauth.urls"))
]

1.4 前端

  • ./templates/login.html
  • ./static/login.js

2、用户用手机QQ扫描QQ登录二维码后,并确认登录后,出现下面错误界面

  • 返回址址:http://www.meiduo.site:8000/oauth_callback?code=62168281346F9B7CBF5964694C5B26F2&state=%2F

  • 根据错误提示,将www.meiduo.site 添加到允许访问的地址列表中,同时还要将127.0.0.1也添加到允许访问的地址列表中

  • 在开发环境下,服务都跑在127.0.0.1上,所以要将本机绑定www.meiduo.site域名

    • Windows系统:编辑 C:\Windows\System32\drivers\etc\hosts
    • 在linux ubuntu系统或者Mac系统:编辑 /etc/hosts

3、接收Authorization Codece,获取openid

  • 用户在QQ登录成功后,QQ会将用户重定向到我们配置的回调网址。
  • 在QQ重定向到回调网址时,会传给我们一个Authorization Code。
  • 我们需要拿到Authorization Code并完成OAuth2.0认证获取openid。
  • 在本项目中,我们申请QQ登录开发资质时配置的回调网址为:
    • http://www.meiduo.site:8000/oauth_callback
    • QQ互联重定向的完整网址为:http://www.meiduo.site:8000/oauth_callback/?code=AE263F12675FA79185B54870D79730A7&state=%2F
  • 使用access_token向QQ服务器请求openid

2.1 view实现

  • 通过QQ回调url,拿到code
  • 通过code ,向QQ服务器申请access_token
  • 通过QQ服务器返回的access_token,再向QQ服务器申请openid
  • 当获得QQ的openid后,就完成QQ登录的验证部分
  • 根据项目需要,还需要将openid与用户名绑定(相关讲解详见后面的4、openid绑定用户的处理)

2.2 路由设置

4、openid是否绑定用户的处理

  • 得到openid后,需要检查openid是否绑定用户,即查询表tb_oauth_qq中是否有openid

    • 得到oauth_user对象,但user对象是它的外键
  • 如果存在,即openid与用户进行了绑定,使用用户操作登录需要的步骤
    • 保持登录状态:利用django的login()
    • 需要获得跳转路径: next关建字改为了state
    • 将用户设置到cookie中
    • 返回前端
  • 如果不存在,即openid未与用户进行了绑定过,需要显示绑定页面
    • 绑定界面:用户名、手机号、密码、图片验证、短信验证、隐藏的openid

      • 隐藏的openid需要后端做为参数传递到前端
    • openid不能用明文传输,需要加密,提交后还需要解密还原
      • 可以使用itsdangerous对openid进行加密及解密

4.1 使用itsdangerous加密和解密

  • 安装itsdangerous : pip install itsdangerous
  • 将加密解密的函数,定义到独立的文件utils.py中
  • 加解密需要用到数据证书,建议用项目配置文件中SECRET_KEY,也可以自定义一个
  • 使用TimedJSONWebSignatureSerializer可以生成带有有效期的token

4.1.1 itsdangerous的使用

  • itsdangerous模块的参考资料链接 http://itsdangerous.readthedocs.io/en/latest/
  • 安装: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': '185xxxxxxx78'})
token = token.decode()
# 检验token
# 验证失败,会抛出itsdangerous.BadData异常
serializer = Serializer(settings.SECRET_KEY, 300)
try:data = serializer.loads(token)
except BadData:return None

4.1.2 itsdangerous加密和解密(utils.py)

# .oauth.utils.py
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from django.conf import settings
from . import constantsdef check_access_token(openid):"""反序列化:param openid: openid密文:return: openid: 明文"""serializer = Serializer(settings.SECRET_KEY, constants.ACCESS_TOKEN_EXPIRES)# constants.ACCESS_TOKEN_EXPIRES=600try:data = serializer.loads(openid)except Exception as e:return Noneelse:return data.get('openid')def generate_access_token(openid):"""签名、序列化openid:param openid: 明文:return: openid密文"""serializer = Serializer(settings.SECRET_KEY, constants.ACCESS_TOKEN_EXPIRES)data = {'openid':  openid}# 类型 是字节token = serializer.dumps(data)return token.decode()

5、views.py代码实现

class QQAuthUserView(View):"""处理QQ登录回调"""def get(self, request):"""处理QQ登录回调的业务逻辑"""code = request.GET.get('code')if not code:return http.HttpResponseForbidden('获取code失败')# 创建工具对象oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,redirect_uri=settings.QQ_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认证失败')# openid QQ用户的ID# 使用openid判断该QQ用户是否绑定商城的用户try:oauth_user = OAuthQQUser.objects.get(openid=openid)except OAuthQQUser.DoesNotExist:# 如果没有找到记录 openid 未绑定商城用户  展示绑定页面# openid 是明文  Sdasdasdasdasy7iyw432 => 明文  可逆 签名的算法context = {'access_token_openid': generate_access_token(openid)}return render(request, 'oauth_callback.html', context=context)else:# 找到记录  登录# 状态保持login(request, oauth_user.user)next = request.GET.get('state')response = redirect(next)response.set_cookie('username', oauth_user.user.username, max_age=3600 * 24)# 响应结果 重定向到首页return response

6、用户绑定实现

  • 用户绑定实现类似于用户注册的业务逻辑
  • 当用户输入的手机号对应的用户已存在
    • 直接将该已存在用户跟openid绑定
  • 当用户输入的手机号对应的用户不存在
    • 新建一个用户,并跟openid绑定

6.1 请求方式

选项 方案
请求方法 POST
请求地址 /oauth_callback/

6.2 请求参数:表单参数

参数名 类型 是否必传 说明
username string 用户名
password string 密码
mobile string 手机号
sms_code string 短信验证码

6.3 响应结果

响应结果 响应内容
注册失败 响应错误提示
注册成功 重定向到首页

6.4 views实现

  • 接收参数

    • 手机号、密码、短信验证码、密文的openid
  • 校验参数
    • 短信验证码是否过期,如果过期,返回错误信息
    • 短信验证码是否正确,如果错误,返回错误信息
    • 解密openid,如果为空(过期或错误),返回错误信息
    • 检查手机号是否存在(即是否注册过)
    • 如果手机没有注册过,以此手机号为用户名创建新用户(用户名=手机,密码,手机号)
    • 如果手机号注册过,判断密码是否正确,如果错误,返回错误
  • 绑定用户
    • 将用记信息与openid保存到数据库中
  • 保持状态
  • 保存cookie
  • 重定向
    def post(self,request):"""实现绑定用户的业务逻辑"""# 接收参数mobile = request.POST.get('mobile')password = request.POST.get('password')sms_code_client = request.POST.get('sms_code')access_token = request.POST.get('access_token_openid')  # openid密文# 校验参数# 判断短信验证码是否一致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是否有效openid = check_access_token(access_token)if not openid:  # 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=password, mobile=mobile)else:# 如果存在,校验密码if not user.check_password(password):return render(request, 'oauth_callback.html', {'account_errmsg': '账号或者密码错误'})# 绑定用户# oauth_qq_user = OAuthQQUser(user=user, openid=openid)# oauth_qq_user.save()try:oauth_qq_user = OAuthQQUser.objects.create(user=user, openid=openid)except Exception as e:return render(request, 'oauth_callback.html', {'account_errmsg': '账号或者密码错误'})# 重定向到首页# 状态保持login(request, oauth_qq_user.user)next = request.GET.get('state')# print(next)response = redirect(next)response.set_cookie('username', oauth_qq_user.user.username, max_age=3600 * 24)# 响应结果 重定向到首页return response

Django项目实践(商城):九、QQ登录相关推荐

  1. Django项目实战----接入第三方QQ登录绑定用户

    需求 用户点击QQ登录接入第三方登录 不需要输入本网站账户就可登录 如果没有绑定过就注册一个 图解 逻辑流程 用户点击QQ登录按钮,后端使用QQLoginTool第三方库来生成一个 QAuthQQ 对 ...

  2. Django项目实战 ----用户使用QQ登录

    QQ登录流程 点击前端QQ登录的请求按钮,弹出扫码页面,用于手机扫码授权 如果之前登录过,那么就直接登录成功 如果是第一次使用QQ登录,会提示绑定之前的账号或者输入手机号 QQ登录流程准备的配置工作 ...

  3. django-happy-shop一个可以快速集成到任何django项目的商城模块

    django-haapy-shop 单看其名称就可以看出,他是一个跟django相关的商城,中间加了一个happy的单词,首先是因为pypi没有与这个重名的包,便于打包上传到pypi:其次,也是非常重 ...

  4. 【愚公系列】2022年01月 Django商城项目13-登录界面-QQ登录功能实现

    文章目录 前言 1.QQ互联开发者申请 2.QQ互联应用申请 3.网站对接QQ登录 一.django实际对接流程 1.创建抽象模型类 2.创建QQ用户模型类 3.注册应用 4.配置QQ登录信息 5.登 ...

  5. django web网站实现第三方QQ登录

    第一步:成为开发者 成为QQ互联的开发者,审核通过才可实现:审核通过后要创建应用,即获取本项目对应与QQ互联的应用ID. QQ登录开发文档:http://wiki.connect.qq.com/准备工 ...

  6. Django项目实践(商城):十一、收货地址

    (根据居然老师直播课内容整理) 一.页面功能简介 在"用户中心"的任一界面,点击左边"收货地址"后,显示下面界面 此界面包括以下4个功能: 新增收货地址 删除当 ...

  7. Django项目实践(商城):十五、商品列表页面

    (根据居然老师直播课内容整理) 一.商品列表页面分析 1.商品频道分类 -已经在"首页广告""首页商品频道分类"中实现,将相关代码封装到contents.uti ...

  8. Django项目实践(商城): 六、生产者消费者设计模式

    (根据居然老师直播课内容整理) 一.生产者消费者设计模式简介 生产者消费者设计模式是一种专门解耦同步问题的设计模式,类似单例设计模式,专门解决某类问题 1.什么是生产者消费者模式 在软件开发的过程中, ...

  9. Django项目实践3 - Django模型(字段、数据库操作及模型继承)

    http://blog.csdn.net/pipisorry/article/details/45725953 Django数据库字段类型(Field types) AutoField class A ...

最新文章

  1. 2020年世界机器人报告
  2. redis cluster集群选主
  3. 网民关注iPhone、Google、微软和安全
  4. 基于stm32f107 stm32cube 和 LWIP 协议实现 udp 组播通信
  5. 轮询没有收到的可能性_轮询(Polling)是什么?
  6. php注册登录遍写入 遍验证,在文件指定行中写入内容的php...-自动注册登录验证机制的php代...-php中出现Undefined index报错的修复方法_169IT.COM...
  7. SQL15 查看学校名称中含北京的用户(通配符使用)
  8. OpenShift 4之评估节点自消耗的系统资源
  9. 将unsigned char字符串以16进制的字符串显示
  10. Python中的图灵机器人
  11. 4.7_singleton_创建型模式:单例模式
  12. ulimit限制 新系统_遇到一个很奇怪的问题,ulimit设置问题
  13. 图片水印 之 二
  14. matlab如何把散点放大,如何在matlab中更新散点3图(循环)
  15. 前馈控制与反馈控制对比
  16. 720视频2码率够吗_两个人去丽江5000够吗,2人去云南旅游5天多少钱(超详细篇)...
  17. conventional-changelog 参数含义
  18. 腾讯云cos对象存储服务文件上传api就是一个大坑
  19. 智联招聘中申请职位之后你根本不知道你申请的职位是啥,而且不想说...
  20. 【机器学习】这份分类决策树算法介绍请收好!

热门文章

  1. PS图片处理:凌乱图片变炫彩背景(转)
  2. [转帖]紫光与群联联盟,长江存储NAND+群联主控+紫光品牌SSD可期
  3. 追星女孩彩虹屁情话合集100条 ✔︎ (二)
  4. leaflet地图原理_使用Leaflet创建地图拓扑图
  5. JavaScript中的闭包 1
  6. 性能与可靠性:Java应用为何像一级方程式赛车
  7. 矢量数据压缩算法“Douglas-Peucker”——递归与非递归实现(python)
  8. EFM32PG22 看门狗导致 芯片串口接收不正常
  9. mac如何启用cpu虚拟化_如何在 Ubuntu 18.04 上安装 KVM
  10. matlab有仿真小灯泡吗,基于Matlab电力变压器励磁涌流的分析和仿真