# 面向资源编程
https://www.shiyanlou.com/v1/books/ # 请求后端 books书籍表中数据
get
post
# 用户表
# 角色表
# 权限表
get/post/put/delete 对应关系
路由 资源(可能对应的是后端路由的 name名称,可以通过name名称解析出对应路由) | 请求方式 | 说明 |
---|---|---|
https://www.shiyanlou.com/v1/books/ | get | 判断用户是否可以查询books表中数据 |
https://www.shiyanlou.com/v1/books/ | post | 判断用户是否可以添加books表中数据 |
https://www.shiyanlou.com/v1/books/ | put | 判断用户是否可以更新books表中数据 |
https://www.shiyanlou.com/v1/books/ | delete | 判断用户是否可以删除books表中数据 |
GET :从服务器取出资源(一项或多项)
POST :在服务器新建一个资源
PUT :在服务器更新资源(客户端提供改变后的完整资源)
PATCH :在服务器更新资源(客户端提供改变的属性)
DELETE:从服务器删除资源
'''1. 2XX请求成功'''
# 200 请求成功,一般用于GET与POST请求
# 201 Created - [POST/PUT/PATCH]:用户新建或修改数据成功。
# 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
# 204 NO CONTENT - [DELETE]:用户删除数据成功。
'''2. 3XX重定向'''
# 301 NO CONTENT - 永久重定向
# 302 NO CONTENT - 临时重定向
'''3. 4XX客户端错误'''
# 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误。
# 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
# 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
# 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录。
# 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
# 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
# 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
'''4. 5XX服务端错误'''
# 500 INTERNAL SERVER ERROR - [*]:服务器内部错误,无法完成请求
# 501 Not Implemented 服务器不支持请求的功能,无法完成请求
```
# 后端的django代码
from django.shortcuts import render
from dwebsocket.decorators import accept_websocket,require_websocket
from django.http import HttpResponse
def index(request):
return render(request, 'index.html')
from dwebsocket.backends.default.websocket import DefaultWebSocket # request.websocket就是DefaultWebSocket对象
tmp = []
# 只有加了这个装饰器,这个视图函数才能处理websocket请求
@accept_websocket
def echo(request):
if not request.is_websocket(): #判断是不是websocket连接
try: #如果是普通的http方法
message = request.GET['message']
return HttpResponse(message)
except:
return render(request,'index.html')
else:
'''1.实现消息推送'''
tmp.append(request.websocket) # 把所有连接的websocket连接都加入列表中
# request.websocket = <dwebsocket.backends.default.websocket.DefaultWebSocket object at 0x00000272E69A4320>
# failed:Invalid frame header:你的视图没有阻塞,请求过一次后服务器端就关闭连接了
# 所以使用for循环 request.websocket 对象就会调用 __iter__()方法,利用迭代器进行阻塞
for message in request.websocket:
for ws in tmp:
ws.send(message)
'''2.实现聊天室思路'''
# d = {} # 使用了一个dict来保存数据,
# d['zhangsan'] = request.websocket # key值是用户身份,value值是dict类型的{username:websocket}。
# d['zhangsan'].send(message) # 发送消息到客户端
# d['lisi'].send(message) ==> request.websocket.send(message)
# 这只是个思路,如果正式使用的话,肯定会对group封装,也不会只保存在内存中,需要保存到redis中去
# 并且对每个websocket对象设置有效期,过期清除,避免长期挂起状态消耗系统资源等
```
```html
# 前端VUE代码
<template>
<div>
<button @click="send">发消息</button>
</div>
</template>
<script>
export default {
data () {
return {
path:"ws://127.0.0.1:8000/echo?username=zhangsan&token=xxxx",
socket:""
}
},
mounted () {
// 初始化
this.init()
},
methods: {
init: function () {
if(typeof(WebSocket) === "undefined"){
alert("您的浏览器不支持socket")
}else{
// 实例化socket
this.socket = new WebSocket(this.path)
// 监听socket连接
this.socket.onopen = this.open
// 监听socket错误信息
this.socket.onerror = this.error
// 监听socket消息
this.socket.onmessage = this.getMessage
}
},
open: function () {
console.log("socket连接成功")
},
error: function () {
console.log("连接错误")
},
getMessage: function (msg) {
console.log(msg.data) // 打印后台返回的数据
},
send: function () {
var params = 'hahahahhahaha';
this.socket.send(params) // 发送给后台的数据
},
close: function () {
console.log("socket已经关闭")
}
},
destroyed () {
// 销毁监听
this.socket.onclose = this.close
}
}
</script>
<style>
</style>
```
1,华为p30,2.0
1,三星s10,5.0
1,小米9,2.6
2,华为p30,1.0
2,vivo,5.0
2,htc,4.6
3,魅族,2.0
3,iphone,5.0
3,pixel2,2.6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
with open('./phone.txt', 'r', encoding='utf-8') as fp:
content = fp.readlines()
# 第一步,将数据读取并格式化为字典形式,便于解析
def parse_data():
with open('./phone.txt','r',encoding='utf-8') as fp:
content = fp.readlines()
# 将用户、评分、和手机写入字典data
data = {}
for line in content:
line = line.strip().split(',')
#如果字典中没有某位用户,则使用用户ID来创建这位用户
if not line[0] in data.keys():
data[line[0]] = {line[1]:line[2]}
#否则直接添加以该用户ID为key字典中
else:
data[line[0]][line[1]] = line[2]
return data
data = parse_data()
'''
{
"1":{
"华为p30":"2.0",
"三星s10":"5.0",
"小米9":"2.6"
},
"2":{
"华为p30":"1.0",
"vivo":"5.0",
"htc":"4.6"
},
"3":{
"魅族":"2.0",
"iphone":"5.0",
"pixel2":"2.6"
}
}
'''
# 第二步:借助"欧几里德"算法计算用户相似度
from math import *
def Euclid(user1, user2):
# 取出两位用户购买过的手机和评分
user1_data = data[user1]
user2_data = data[user2]
distance = 0
# 找到两位用户都购买过的手机,并计算欧式距离
for key in user1_data.keys():
if key in user2_data.keys():
# 注意,distance越大表示两者越相似
distance += pow(float(user1_data[key]) - float(user2_data[key]), 2)
return 1 / (1 + sqrt(distance)) # 这里返回值越小,相似度越大
# 第三步:计算某个用户与其他用户的相似度
def top_simliar(userID):
res = []
for userid in data.keys():
#排除与自己计算相似度
if not userid == userID:
simliar = Euclid(userID,userid)
res.append((userid,simliar)) # res = # [('2', 0.5), ('3', 1.0)]
res.sort(key=lambda val:val[1])
return res
# 第四步:根据相似度最高的用户喜好商品排序,把相似度最高用户的喜好推荐给当前用户
def recommend(userid):
#相似度最高的用户
top_sim_user = top_simliar(userid)[0][0] # top_sim_user=2 找到相似度最高的用户ID
#相似度最高的用户的购买记录
items = data[top_sim_user] # items = {'华为p30': '1.0', 'vivo': '5.0', 'htc': '4.6'}
recommendations = []
#筛选出该用户未购买的手机并添加到列表中
for item in items.keys():
if item not in data[userid].keys():
recommendations.append((item,items[item]))
recommendations.sort(key=lambda val:val[1],reverse=True)#按照评分排序
return recommendations
if __name__ == '__main__':
# 找到与用户id为1的用户相似度最高的用户
print(recommend('1')) # [('vivo', '5.0'), ('htc', '4.6')]
https://blog.kido.site/2018/12/01/db-and-cache-01/
https://blog.csdn.net/simba_1986/article/details/77823309
场景一:对数据实时性要求不高,更新不频繁
读取数据:先判断当前是否有缓存(通常是根据key来判断),如果存在则从redis缓存读取,如果没有缓存,则从mysql中读取并重新写入缓存。
更新数据:同样首先判断是否有缓存,如果有则更新redis中的缓存,然后再更新mysql数据库,如果没有缓存,则直接更新mysql数据库。
场景二:高并发,更新频繁(如果用户1更新数据时,会先删除缓存,然后更新mysql,在mysql更新还没完成的时候,用户2来查询数据,查询完mysql后会写入缓存,此时写入的缓存是mysql更新前的数据,接着用户1完成了更新mysql的操作,造成了mysql和缓存redis数据不一致的问题)
解决方案:使用队列,根据商品的ID去做hash值,然后对队列个数取模,当有数据更新请求时,先把它丢到队列里去,当更新完后再从队列里去除,如果在更新的过程中,遇到以上场景,先去缓存里看下有没有数据,如果没有,可以先去队列里看是否有相同商品ID正在进行更新,如果有某个商品正在更新同时又有查询这个商品的请求,就把查询的请求放到队列里,然后同步等待缓存更新完成。
这里有一个优化点,如果发现队列里有一个查询请求了,那么就不要放新的查询操作进去了,用一个while(true)循环去查询缓存,循环个200MS左右。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有