当前位置: 首页 > news >正文

使用QQ登录(头条项目-09)

一 QQ登录开发文档

QQ登录:即我们所说的 第三⽅登录,是指⽤户可以不在本项⽬中输⼊密码,⽽直接 通过第三⽅的验证,成功登录本项⽬。

1.1 QQ互联开发者申请步骤

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

qq开发文档链接

1.2 QQ互联应⽤申请步骤

成为QQ互联开发者后,还需 创建应⽤,即 获取本项⽬对应与QQ互联的应⽤ID

创建应用

1.3 ⽹站接⼊QQ登录功能实现

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

开发文档准备工作

1.4 QQ登录流程分析

1.5 知识要点

当我们在对接第三⽅平台的接⼝时,⼀定要认真阅读 第三⽅平台提供的⽂档。⽂档 中⼀定会有接⼝的使⽤说明,⽅便我们开发。

二 定义QQ登录模型类

QQ登录成功后,我们需要 将QQ⽤户和芒果头条⽤户 关联 到⼀起,⽅便下次QQ登录 时使⽤,所以我们选择 使⽤MySQL数据库进⾏存储

2.1 定义模型类基类

为了给项⽬中模型类补充 数据创建时间和更新时间两个字段,我们需要 定义模型类 基类。 在mgproject.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:# 说明是抽象模型类, ⽤于继承使⽤,数据库迁移时不会 创建BaseModel的表abstract = True

2.2 定义QQ登录模型类

创建⼀个新的应⽤oauth,⽤来实现QQ第三⽅认证登录。

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

在oauth/models.py中 定义QQ身份(openid)与⽤户模型类Users的关联关系。

from django.db import models
from mgproject.utils.models import BaseModel# Create your models here
class OAuthQQUser(BaseModel):"""QQ登录⽤户数据"""user = models.ForeignKey('userapp.Users',on_delete=models.CASCADE, verbose_name='⽤户')openid = models.CharField(max_length=64, verbose_name='openid',db_index=True)class Meta:db_table = 'tb_oauth_qq'verbose_name = 'QQ登录⽤户数据'verbose_name_plural = verbose_name

2.3 迁移QQ登录模型类

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

三 QQ登录工具AgentLogin

3.1 AgentLogin介绍

⽬前 只⽀持 腾讯QQ,微信,微博 的第三⽅登录

该⼯具封装了QQ登录 时对接QQ互联接⼝的 请求操作。可⽤于快速实现QQ登录功能。

3.2 AgentLogin安装

pip install AgentLogin

3.3 AgentLogin 使⽤说明

from AgentLogin import AgentLogin# 获取扫码⻚⾯地址
qq_url = AgentLogin.qq_url(client_id, redirect_uri)
# <a href="{{ qq_url }}">QQ登录<a>
# client_id:QQ互联上应⽤的APPID
# redirect_uri: QQ互联上应⽤的⽹站回调域# 获取⽤户名和openid
AgentLogin.qq(client_id, client_secret, url, code)
# 获取⽤户所有信息
AgentLogin.all_qq(client_id, client_secret, url, code)
# client_id: QQ互联上应⽤的 APPID
# client_secret: QQ互联上应⽤的APP Key
# url: QQ互联上应⽤的⽹站回调域
# code: 从QQ服务器得到code
# 注意此code会在10分钟内过期AgentLogin.all_qq(settings.QQ_CLIENT_ID, settings.QQ_APP_KEY, settings.QQ_REDIRECT_URI, code)

四 通过OAuth2.0认证 获取openid

  • 提取code 请求参数
  • 使⽤code向QQ服务器请求 access_token
  • 使⽤access_token向QQ服务器请求 openid
  • 使⽤openid查询 该QQ⽤户是否芒果头条中 绑定过⽤户
  • 如果openid已绑定 芒果头条⽤户,直接⽣成JWT token,并返回
  • 如果openid没绑定 芒果头条⽤户,创建⽤户并绑定到openid

4.1 获取QQ登录扫码⻚⾯

4.1.1 请求⽅式
选项⽅案
请求⽅法GET
请求地址/qq/login/
4.1.2 请求参数:⽆
4.1.3 响应结果:JSON
字段说明
code状态码
errmsg错误信息
login_urlQQ登录扫码⻚⾯链接
4.1.4 后端逻辑实现
class QQLoginURLView(View):"""提供QQ登录⻚⾯⽹址"""def get(self, request):# 获取QQ登录⻚⾯⽹址qq_login_url = AgentLogin.qq_url(settings.QQ_CLIENT_ID, settings.QQ_REDIRECT_URI)return http.JsonResponse({'code': 200, 'errmsg': 'OK','qq_login_url': qq_login_url})
4.1.5 QQ登录参数
# QQ登录的配置参数
QQ_CLIENT_ID = '101917966'
QQ_REDIRECT_URI = 'http://www.nagle.cn:8083/about'
QQ_APP_KEY = '20fcc768255829c08fa4efbe8acf0001'

4.2 接收Authorization Code

提示:

  • ⽤户在QQ登录成功后,QQ会 将⽤户重定向到我们配置的回调⽹址
  • 在QQ 重定向到回调⽹址时会传给我们⼀个Authorization Code
  • 我们需要拿到Authorization Code并 完成OAuth2.0认证获取openid
  • 在本项⽬中,我们申请QQ登录开发资质时配置的 回调⽹址 为:
    • http://www.nagle.cn:8083/about
  • QQ互联重定向的 完整⽹址 为:
    • http://www.nagle.cn/about/? code=991088ECBF489B38CFBDF1BB4B093EC9
class QQLoginUserView(View):"""⽤户扫码登录的回调处理"""def get(self, request):"""Oauth2.0认证"""# 接收Authorization Codecode = request.GET.get('code')if not code:raise Forbbiden('缺少code')pass
re_path(r'^about/$', views.QQLoginUserView.as_view()),

4.3 OAuth2.0认证 获取openid

import logging
from django import httplogger = logging.getLogger('django')class QQLoginUserView(View):"""⽤户扫码登录的回调处理"""def get(self, request):"""Oauth2.0认证"""# 接收Authorization Codecode = request.GET.get('code')if not code:return http.HttpResponseForbidden('缺少code')try:nickname, openid = AgentLogin.qq(settings.QQ_CLIENT_ID, settings.QQ_APP_KEY, settings.QQ_REDIRECT_URI, code)except Exception as e:logger.error(e)return http.HttpResponseServerError('OAuth2.0认证失败')pass

4.4 本机绑定www.nagle.cn域名

1.ubuntu系统或者Mac系统

sudo vi /etc/hosts
127.0.0.1 www.nagle.cn

4.5 修改 dev.py 配置⽂件

ALLOWED_HOSTS = ['www.nagle.cn','127.0.0.1']

4.6 修改服务器端⼝号

4.7 配置回调地址路由

# oauth/urls.py
re_path('^about/$',views.QQAuthUserView.as_view()),

4.8 创建类视图

class QQAuthUserView(View):def get(self, request):"""获取openid:param request::return:"""# 获取code参数code = request.GET.get('code', '')# 校验参数if not code:return http.HttpResponseForbidden('缺少code参数值')# 调⽤接⼝⽅法获取openidnickname, openid = AgentLogin.qq(settings.QQ_CLIENT_ID, settings.QQ_APP_KEY,settings.QQ_REDIRECT_URI, code)return HttpResponse(openid)

五 QQ用户 是否绑定项目用户 的处理

5.1 判断 openid是否绑定过⽤户

使⽤openid 查询该QQ⽤户是否在芒果头条中绑定过⽤户

try:oauth_user = OAuthQQUser.objects.get(openid=openid)
except OAuthQQUser.DoesNotExist:# 如果openid没绑定芒果头条⽤户pass
else:# 如果openid已绑定芒果头条⽤户pass

5.2 openid 已绑定⽤户的处理

如果openid已绑定芒果头条⽤户,直接⽣成状态保持信息,登录成功,并 重定向到⾸⻚

class QQOauthUser(View):def get(self, request):# 获取code参数code = request.GET.get('code', '')if code == '':return http.HttpResponseForbidden('缺少参数')# 获取QQ⽤户名和openidnickname, openid = AgentLogin.qq(settings.QQ_CLIENT_ID, settings.QQ_APP_KEY, settings.QQ_REDIRECT_URI, code)try:# 查询当前QQ⽤户是否绑定芒果头条⽤户qq_user = QQAuthUser.objects.get(openid=openid)except QQAuthUser.DoesNotExist:# 没绑定芒果头条⽤户passelse:# 已绑定芒果头条⽤户# 实现状态保持mg_user = qq_user.userlogin(request, mg_user)# 响应结果return redirect(reverse('newsapp:index'))

5.3 openid 未绑定⽤户的处理

  • 为了能够在后续的绑定⽤户操作前端可以使⽤openid,在这⾥将openid签名后响应给前端
  • openid属于⽤户的隐私信息,所以需要将openid签名处理,避免暴露。
class QQOauthUser(View):def get(self, request):# 获取code参数code = request.GET.get('code', '')if code == '':return http.HttpResponseForbidden('缺少参数')# 获取QQ⽤户名和openidnickname, openid = AgentLogin.qq(settings.QQ_CLIENT_ID, settings.QQ_APP_KEY,settings.QQ_REDIRECT_URI, code)try:# 查询当前QQ⽤户是否绑定芒果头条⽤户qq_user = QQAuthUser.objects.get(openid=openid)except QQAuthUser.DoesNotExist:# 没绑定芒果头条⽤户# 加密openid数据sec_openid = generate_secret_openid(openid)return render(request, 'oauth/oauth_user.html',{'sec_openid': sec_openid})else:# 已绑定芒果头条⽤户# 实现状态保持mg_user = qq_user.userlogin(request, mg_user)# 响应结果return redirect(reverse('newsapp:index'))
# oauth/oauth_user.html 
<input type="hidden" name="sec_openid" value="{{ sec_openid }}">

5.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({'uname': 'zhangsan'})
token = token.decode()
# 检验token
# 验证失败,会抛出itsdangerous.BadData异常
serializer = Serializer(settings.SECRET_KEY, 300)
try:data = serializer.loads(token)
except BadData:return None
  • openid签名处理 (对openid进⾏ 加密)
# oauth/utils.py
def generate_secret_openid(openid):"""签名openid:param openid: ⽤户的openid:return: access_token"""# 创建序列化器对象给数据加密serializer = Serializer(settings.SECRET_KEY, expires_in=600)data = {'openid': openid}token = serializer.dumps(data)return token.decode()

六 QQ用户绑定项目 用户实现

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

  • 当⽤户输⼊的⼿机号对应的 ⽤户已存在
    • 直接 将该已存在⽤户跟openid绑定
  • 当⽤户输⼊的⼿机号对应的 ⽤户不存在
    • 新建⼀个⽤户,并跟openid绑定
# /qq/login/ POST
# oauth/views.py
class QQLoginUserView(View):"""⽤户扫码登录的回调处理"""def get(self, request):"""Oauth2.0认证"""......def post(self, request):"""QQ⽤户登录成功后绑定芒果头条⽤户"""# 接收参数phone = request.POST.get('phone')pwd = request.POST.get('password')sms_code_client = request.POST.get('msgcode')sec_openid = request.POST.get('sec_openid')# 校验参数# 判断参数是否⻬全if not all([phone, pwd, sms_code_client, sec_openid]):return http.HttpResponseForbidden('缺少必传参数')# 判断⼿机号是否合法if not re.match(r'^1[35789]\d{9}$', phone):return http.HttpResponseForbidden('请输⼊正确的⼿机号码')# 判断密码是否合格if not re.match(r'^[0-9A-Za-z]{3,8}$', pwd):return http.HttpResponseForbidden('请输⼊3,8位的密码')# 判断短信验证码是否⼀致redis_conn = get_redis_connection('verify_code')sms_code_server = redis_conn.get('sms_%s' % phone)if sms_code_server is None:return render(request, 'oauth/oauth_user.html',{'sms_code_errmsg': '⽆效的短信验证码'})if sms_code_client != sms_code_server.decode():return render(request, 'oauth/oauth_user.html',{'sms_code_errmsg': '输⼊短信验证码有误'})# 判断openid是否有效:错误提示放在sms_code_errmsg位置openid = check_secret_openid(sec_openid)if not openid:return render(request, 'oauth/oauth_user.html',{'openid_errmsg': '⽆效的openid'})# 保存注册数据try:user = Users.objects.get(phone=phone)except Users.DoesNotExist:# ⽤户不存在,新建⽤户user = Users.objects.create_user(username=phone,password=pwd, phone=phone)else:# 如果⽤户存在,检查⽤户密码if not user.check_password(pwd):return render(request, 'oauth/oauth_user.html',{'account_errmsg': '⽤户名或密码错误'})# 将⽤户绑定openidtry:QQAuthUser.objects.create(openid=openid, user=user)except DatabaseError:return render(request, 'oauth/oauth_user.html',{'qq_login_errmsg': 'QQ登录失败'})# 实现状态保持login(request, user)# 响应绑定结果return redirect(reverse('newsapp:index'))

 

七 添加邮箱前端逻辑

7.1 前端逻辑处理

1.user_center.js

methods: {// 获取指定名称的cookie值getCookie: function(name) {var value = '; ' + document.cookie;var parts = value.split('; ' + name + '=');if (parts.length === 2) {// 返回cookie值return parts.pop().split(';').shift();}// 如果没有找到对应的cookie,返回nullreturn null;},// 保存邮箱save_email: function() {// 使用axios发送post请求axios.post('/emails/', {'email': this.email,'userid': this.userid}, {headers: {// 从cookie中获取csrftoken并设置到请求头中,解决跨域问题'X-CSRFToken': this.getCookie('csrftoken')}}).then(response => {// 请求成功后的处理if (response.data.code == '200') {// 如果返回码为200,表示成功,刷新页面location.reload();this.error_email = false;} else {// 否则标记邮箱保存出错this.error_email = true;}}).catch(error => {// 请求失败后的处理,打印错误信息console.log(error.response);});}
}

2.user_center.html

<table border="0" cellpadding="0" cellspacing="0"><tr><td width="30%">⽤户名</td><td>{{ user.username }}</td></tr><tr><td>⼿机号</td><td>{{ user.phone }}</td></tr><tr><td>邮箱</td><td>{% if user.email %}{{ user.email}}{% else %}<input type="text" v-model="email" style="width: 290px;" placeholder="输⼊邮箱地址"><button @click="save_email">保存</button><span class="error-tip" v-show="error_email">${error_email_msg}</span>{% endif %}</td></tr>
</table>
<script>// 别忘了加""号let userid = "{{ user.id }}";
</script>
<script type="text/javascript" src="{% static 'js/userapp/user_center.js' %}"></script>

7.2 添加邮箱后端逻辑

7.2.1 添加邮箱后端接⼝设计
选项⽅案
请求⽅法POST
请求地址/emails/
7.2.2 请求参数:json参数
参数名类型是否必传说明
emailstring邮箱地址
useridstring当前登录⽤户id
7.2.3 响应结果:JSON
字段说明
code状态码
errmsg错误信息

7.3 添加邮箱后端实现

7.3.1 配置路由
# userapp/urls.py
re_path('^emails/$',views.EmailView.as_view()),
7.3.2 创建视图
# userapp/views.py
class EmailView(View):def post(self, request):params_str = request.body.decode()if params_str:p_dict = json.loads(params_str)count = Users.objects.filter(id=p_dict['userid']).update(email=p_dict['email'])if count:return JsonResponse({'code': 200, 'errormsg': 'OK'})return JsonResponse({'code': 500, 'errormsg': '保存邮箱地址失败!'})

相关文章:

使用QQ登录(头条项目-09)

一 QQ登录开发文档 QQ登录&#xff1a;即我们所说的 第三⽅登录&#xff0c;是指⽤户可以不在本项⽬中输⼊密码&#xff0c;⽽直接 通过第三⽅的验证&#xff0c;成功登录本项⽬。 1.1 QQ互联开发者申请步骤 若想实现QQ登录&#xff0c;需要成为 QQ互联的开发者&#xff0c;…...

iOS页面设计:UIScrollView布局问题与应对策略

在iOS开发中&#xff0c;UIScrollView是一个极其重要且常用的控件&#xff0c;它允许用户通过手势滑动查看大量内容。然而&#xff0c;在利用UIScrollView进行页面布局时&#xff0c;开发者往往会遇到一些挑战。本文将深入探讨UIScrollView布局中常见的问题&#xff0c;并提供相…...

Linux提权-02 sudo提权

文章目录 1. sudo 提权原理1.1 原理1.2 sudo文件配置 2. 提权利用方式2.1 sudo权限分配不当2.2 sudo脚本篡改2.3 sudo脚本参数利用2.4 sudo绕过路径执行2.5 sudo LD_PRELOAD环境变量2.6 sudo caching2.7 sudo令牌进程注入 3. 参考 1. sudo 提权原理 1.1 原理 sudo是一个用于在…...

vscode 设置

一、如何在vscode中设置放大缩小代码 1.1.文件—首选项——设置 1.2.在搜索框里输入“Font Ligatures”&#xff0c;然后点击"在settings.json中编辑" 1.3.在setting中&#xff08;"editor.fontLigatures":前&#xff09;添加如下代码 "editor.mous…...

学习threejs,使用FlyControls相机控制器

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.FlyControls 相机控制…...

在 C++ 中实现调试日志输出

在 C 编程中&#xff0c;调试日志对于定位问题和优化代码至关重要。有效的调试日志不仅能帮助我们快速定位错误&#xff0c;还能提供有关程序运行状态的有价值的信息。本文将介绍几种常用的调试日志输出方法&#xff0c;并教你如何在日志中添加时间戳。 1. 使用 #ifdef _DEBUG…...

从零搭建一套远程手机的桌面操控和文件传输的小工具

从零搭建一套远程手机的桌面操控和文件传输的小工具 --ADB连接专题 一、前言 前面的篇章中&#xff0c;我们确定了通过基于TCP连接的ADB控制远程手机的操作思路。本篇中我们将进行实际的ADB桥接的具体链路搭建工作&#xff0c;从原理和实际部署和操作层面上&#xff0c;从零…...

Python中的静态方法

目录 什么是静态方法&#xff1f;静态方法的特点 定义和调用静态方法示例&#xff1a;定义一个简单的静态方法 静态方法 vs 类方法 vs 实例方法示例对比 静态方法的应用场景1. &#x1f527; 工具函数2. &#x1f3ed; 工厂方法3. ✅ 数据验证 静态方法的限制总结 静态方法是 P…...

【C++】面试题整理(未完待续)

【C】面试题整理 文章目录 一、概述二、C基础2.1 - 指针在 32 位和 64 位系统中的长度2.2 - 数组和指针2.3 - 结构体对齐补齐2.4 - 头文件包含2.5 - 堆和栈的区别2.6 - 宏函数比较两个数值的大小2.7 - 冒泡排序2.8 - 菱形继承的内存布局2.9 - 继承重写2.10 - 如何禁止类在栈上分…...

每日一题 403. 青蛙过河

403. 青蛙过河 动态规划&#xff0c;状态转移 和 上一步步长 和 当前位置点 有关系 class Solution { public:bool canCross(vector<int>& stones) {int n stones.size();unordered_map<int,unordered_set<int>> dp;unordered_map<int,int> mp;…...

Spring Boot 集成 MongoDB:启动即注入的便捷实践

引言 在现代后端开发中&#xff0c;Spring Boot 凭借其快速开发、自动配置等特性深受开发者喜爱&#xff0c;而 MongoDB 以其灵活的文档存储结构和出色的扩展性&#xff0c;成为处理非结构化数据的首选数据库之一。将两者结合&#xff0c;利用 Spring Boot 的自动配置功能&…...

【电视盒子】HI3798MV300刷机教程笔记/备份遥控码修复遥控器/ADB/线刷卡刷/电视盒子安装第三方应用软件

心血来潮&#xff0c;看到电视机顶盒满天飞的广告&#xff0c;想改造一下家里的电视盒子&#xff0c;学一下网上的人刷机&#xff0c;但是一切都不知道怎么开始&#xff0c;虽然折腾了一天&#xff0c;以失败告终&#xff0c;还是做点刷机笔记。 0.我的机器 年少不会甄别&…...

R语言的文件操作

R语言的文件操作 引言 在数据科学和分析的过程中&#xff0c;文件操作是不可或缺的一部分。R语言作为一种强大的统计计算和图形作图的编程语言&#xff0c;提供了丰富的文件操作函数&#xff0c;使得用户能够方便地读取和保存数据。本文将详细介绍R语言中的文件操作&#xff…...

锐捷路由器网关RG-NBR6135-E和锐捷交换机 Ruijie Reyee RG-ES224GC 电脑登录web方法

2025年1月17日22:29:35 最近淘了点东西&#xff0c;准备在家里搞一套深度学习的服务器&#xff0c;先把网关和交换机搞到了 锐捷路由器网关RG-NBR6135-E 电脑登录web方法 在拿到机器的时候&#xff0c;如果不是全新建议拿根牙签&#xff0c;差入reset 5-10秒,灯光会全部闪几下…...

论文速读|NoteLLM: A Retrievable Large Language Model for Note Recommendation.WWW24

论文地址&#xff1a;https://arxiv.org/abs/2403.01744 bib引用&#xff1a; misc{zhang2024notellmretrievablelargelanguage,title{NoteLLM: A Retrievable Large Language Model for Note Recommendation}, author{Chao Zhang and Shiwei Wu and Haoxin Zhang and Tong Xu…...

在线图片转为excel工具

在线图片转为excel工具&#xff0c;无需登录&#xff0c;无需成本&#xff0c;用完就走。 包括中文和英文版本。 官网地址&#xff1a; https://img2excel.openai2025.com 效果&#xff1a;...

深度学习篇---数据集分类

文章目录 前言第一部分&#xff1a;VOC数据集标签、COCO数据集格式1.VOC数据集标签的特点及优缺点特点优点缺点 2.COCO数据集标签的特点及优缺点特点优点缺点 3.YOLO数据集标签的特点及优缺点特点优点缺点 第二部分&#xff1a;VOC格式和YOLO格式1.VOC格式3.YOLO格式3.区别(1)文…...

Unity3D仿星露谷物语开发23之拿起道具的动画

1、目标 当点击库存栏上可以carry的道具时&#xff0c;首先arms替换为carry状态&#xff0c;同时手上拿着被点击的道具。当再次点击同一个道具时&#xff0c;ams替换为idle状态&#xff0c;手上放下之前的道具。 这个最主要的是要学会使用AnimatorOverrideController类。 2、…...

素描风格渲染

素描风格渲染&#xff08;Hatching Style Rendering&#xff09;&#xff0c;是一种非真实感渲染&#xff08;NPR&#xff09;&#xff0c;主要目的是使3D模型看起来像 手绘素描的视觉效果。这种风格的渲染常用于游戏、动画和电影中&#xff0c;用来创造一种独特的艺术风格 1、…...

STM32使用DSP库 Keil方式添加

文章目录 前言一、添加DSP库二、使能FPU及配置1. 使能FPU2. 增加编译的宏3.增加头文件的检索路径三. 验证1. 源码中添加2.代码测试前言 添加DSP有两种方案,本文采用的是是Keil 中添加。 一、添加DSP库 在创建好的工程中添加DSP库:步骤如下: 步骤1:选择运行环境管理; 步…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一&#xff1a;yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因&#xff0c;后面把yaml.safe_dump直接替换成yaml.dump&#xff0c;确实能保存&#xff0c;但出现乱码&#xff1a; 放弃yaml.dump&#xff0c;又切…...