使用Redis构建简易社交网站(2)-处理用户关系

目的

本文目的:实现用户关注和取消关注功能。(完整代码附在文章末尾)

相关知识

在我之前的文章 《使用Redis构建简易社交网站(1)-创建用户与动态界面》中提到了如何实现简易社交网站中创建新用户和创建新动态功能。

那这篇文章将教会你掌握:1.redis基本命令,2.python基本命令。

redis基本命令

zscore:返回有序集合中指定成员的分值。

conn = redis.Redis()
conn.zscore("testzset", "member1")
conn.zscore("testzset", "not_exists_member")

testzset内容如下:

执行结果:

100.0
None

zadd:将成员加入到有序集合中,并确保其在正确的位置上。

conn = redis.Redis()
conn.zadd("testzset", "member2", 3)
conn.zadd("testzset", "member1", 2)
conn.zadd("testzset", "member3", 1)

执行后:

member3
member1
member2

执行结果:111

hincrby:为哈希中指定域的值增加增量 increment,用于统计。

conn = redis.Redis()
conn.hincrby("testhash", "field1", 1)

执行前:

{'field1': '1'}

执行后:

{'field1': '2'}

zrem:从有序集合中移除指定成员。

conn = redis.Redis()
conn.zrem("testzset", "member1")

执行前:

member3
member1
member2

执行后:

member3
member2

执行结果:1

pipeline:将多条命令按照先后顺序放进一个队列中,一般配合execute一同使用,原子性(atomic)地执行队列里的命令。

conn = redis.Redis()
pipe = conn.pipeline(True) # 事务开始
pipe.incr("counter")
pipe.incr("counter")
pipe.incr("counter")
pipe.execute() # 事务执行

执行结果:[1, 2, 3],通过下标即可获取对应命令的执行结果。

python基本命令

使用格式化拼接字符串:

"My name is %s, I'm %i years old"%('educoder', 2)

执行结果:"My name is educoder, I'm 2 years old"

返回当前时间的时间戳。

  1. time.time()

将字符串转换为整型数据:

  1. int("1")

执行结果:1

取一个数的相反数:

  1. a = 1
  2. b = -a
  3. print b

执行结果:-1

实战例题

编写 follow(uid, other_uid) 函数,实现关注用户的功能,具体参数与要求如下:

  • 方法参数uid为当前用户编号,other_uid为被关注的用户编号;
  • 避免重复关注的实现:如果被关注的用户编号已经在当前用户的关注列表following:{uid}中,则不重复关注,直接返回None
  • 建立关注关系的实现:使用事务一次性提交:
    • 将被关注的用户编号加入到当前用户的关注列表following:{uid}中,分值为当前时间戳。
    • 将当前用户编号加入到被关注用户的粉丝列表中followers:{other_uid},分值为当前时间戳。
  • 修改统计数据的实现:若关系建立成功,则使用事务一次性提交:
    • 将当前用户详情user:{uid}中的关注数following1
    • 将被关注用户详情user:{other_uid}中的粉丝数followers1
  • 返回执行结果的实现:返回True

编写 unfollow(uid, other_uid) 函数,实现取消关注的功能,具体参数与要求如下:

  • 方法参数uid为当前用户编号,other_uid为被取消关注的用户编号;
  • 避免重复取消关注的实现:如果被关注的用户编号已经不在当前用户的关注列表following:{uid}中,则不重复取消关注,直接返回None
  • 删除关注关系的实现:使用事务一次性提交:
    • 从当前用户的关注列表following:{uid}中移除被取消关注用户编号。
    • 从被取消关注用户的粉丝列表中followers:{other_uid}移除当前用户编号。
  • 修改统计数据的实现:若关系删除成功,则使用事务一次性提交:
    • 将当前用户详情user:{uid}中的关注数following1
    • 将被取消关注用户详情user:{other_uid}中的粉丝数followers1
  • 返回执行结果的实现:返回True

注意: 关注列表和粉丝列表均为有序集合,存储成员时,分值均为当前时间戳; 用户详情为上一关中创建的哈希结构。

测试输入:

  1. 9
  2. 4

预期输出:

测试 follow 方法...
用户 9 关注 用户 4
关注结果: True
用户 9 的关注列表内容为: ['4']
用户 4 的粉丝列表内容为: ['9']
用户 9 的用户详情为: {'login_name': 'test_user9', 'posts': '0', 'real_name': 'Test user9', 'followers': '0', 'following': '1', 'id': '9'}
用户 4 的用户详情为: {'login_name': 'test_user4', 'posts': '0', 'real_name': 'Test user4', 'followers': '1', 'following': '0', 'id': '4'}用户 9 再次关注 用户 4
关注结果: None测试 unfollow 方法...
用户 9 取消关注 用户 4
取消关注结果: True
用户 9 的关注列表内容为: []
用户 4 的粉丝列表内容为: []
用户 9 的用户详情为: {'login_name': 'test_user9', 'posts': '0', 'real_name': 'Test user9', 'followers': '0', 'following': '0', 'id': '9'}
用户 4 的用户详情为: {'login_name': 'test_user4', 'posts': '0', 'real_name': 'Test user4', 'followers': '0', 'following': '0', 'id': '4'}用户 9 再次取消关注 用户 4
取消关注结果: None

 code.py

#code.py
#-*- coding:utf-8 -*-import re
import time
import redisconn = redis.Redis()# 关注用户
def follow(uid, other_uid):# 请在下面完成要求的功能#********* Begin *********#fkey1 = "following:%s"%(uid)fkey2 = "followers:%s"%(other_uid)if conn.zscore(fkey1, other_uid):return Nonenow = time.time()pipe = conn.pipeline(True)pipe.zadd(fkey1, other_uid, now)pipe.zadd(fkey2, uid, now)following, followers = pipe.execute()pipe.hincrby("user:%s"%(uid), 'following', int(following))pipe.hincrby("user:%s"%(other_uid), 'followers', int(followers))pipe.execute()return True#********* End *********## 取消关注
def unfollow(uid, other_uid):# 请在下面完成要求的功能#********* Begin *********#fkey1 = "following:%s"%(uid)fkey2 = "followers:%s"%(other_uid)if not conn.zscore(fkey1, other_uid):return Nonepipe = conn.pipeline(True)pipe.zrem(fkey1, other_uid)pipe.zrem(fkey2, uid)following, followers = pipe.execute()pipe.hincrby("user:%s"%(uid), 'following', -int(following))pipe.hincrby("user:%s"%(other_uid), 'followers', -int(followers))pipe.execute()return True#********* End *********## 创建新用户
def create_user(login_name, real_name):login_name = login_name.lower()if conn.hget("users", login_name):return Noneuid = conn.incr("user:id")pipe = conn.pipeline(True)pipe.hset("users", login_name, uid)pipe.hmset("user:%i"%(uid), {'login_name': login_name,'id': uid,'real_name': real_name,'followers': 0,'following': 0,'posts': 0,'last_signup': time.time(),})pipe.execute()return uid# 为用户创建新动态
def create_post(uid, content):pipe = conn.pipeline(True)pipe.hget("user:%i"%(uid), 'login_name')pipe.incr("post:id")login_name, pid = pipe.execute()if not login_name:return Nonepipe.hmset("post:%i"%(pid), {'id': pid,'uid': uid,'content': content,'posted': time.time(),'user_name': login_name,})pipe.hincrby("user:%i"%(uid), 'posts')pipe.execute()return pid

read.py

#read.py
#-*- coding:utf-8 -*-import os
import sys
import time
import redis
import pprint
from code import *conn = redis.Redis()
retry_time = 0
while True:try:conn.ping()breakexcept redis.exceptions.ConnectionError:os.system("redis-server > /dev/null 2>&1 &")retry_time += 1if retry_time > 3:breakpipe = conn.pipeline(True)
pipe.delete("users", "user:id")
keys = conn.keys("user:*") + conn.keys("followers:*") + conn.keys("following:*")
for key in keys:pipe.delete(key)
pipe.execute()# 创建测试数据
join_str = " "
for i in xrange(10):login_name = "test_user%i"%(i+1)real_name = join_str.join(login_name.split("_")).capitalize()create_user(login_name, real_name)uid = int(sys.stdin.readline().strip())
other_uid = int(sys.stdin.readline().strip())print "测试 follow 方法..."
print "用户 %i 关注 用户 %i"%(uid, other_uid)
f_result = follow(uid, other_uid)
print "关注结果: " + str(f_result)
print "用户 %i 的关注列表内容为: %s"%(uid, str(conn.zrange("following:%i"%(uid), 0, -1)))
print "用户 %i 的粉丝列表内容为: %s"%(other_uid, str(conn.zrange("followers:%i"%(other_uid), 0, -1)))
uid_info = conn.hgetall("user:%i"%(uid))
uid_info.pop("last_signup", "404")
other_uid_info = conn.hgetall("user:%i"%(other_uid))
other_uid_info.pop("last_signup", "404")
print "用户 %i 的用户详情为: %s"%(uid, str(uid_info))
print "用户 %i 的用户详情为: %s"%(other_uid, str(other_uid_info))
printprint "用户 %i 再次关注 用户 %i"%(uid, other_uid)
oth_f_result = follow(uid, other_uid)
print "关注结果: " + str(oth_f_result)
printprint "测试 unfollow 方法..."
print "用户 %i 取消关注 用户 %i"%(uid, other_uid)
unf_result = unfollow(uid, other_uid)
print "取消关注结果: " + str(unf_result)
print "用户 %i 的关注列表内容为: %s"%(uid, str(conn.zrange("following:%i"%(uid), 0, -1)))
print "用户 %i 的粉丝列表内容为: %s"%(other_uid, str(conn.zrange("followers:%i"%(other_uid), 0, -1)))
uid_info = conn.hgetall("user:%i"%(uid))
uid_info.pop("last_signup", "404")
other_uid_info = conn.hgetall("user:%i"%(other_uid))
other_uid_info.pop("last_signup", "404")
print "用户 %i 的用户详情为: %s"%(uid, str(uid_info))
print "用户 %i 的用户详情为: %s"%(other_uid, str(other_uid_info))
printprint "用户 %i 再次取消关注 用户 %i"%(uid, other_uid)
oth_unf_result = unfollow(uid, other_uid)
print "取消关注结果: " + str(oth_unf_result)pipe = conn.pipeline(True)
pipe.delete("users", "user:id")
keys = conn.keys("user:*") + conn.keys("followers:*") + conn.keys("following:*")
for key in keys:pipe.delete(key)
pipe.execute()

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

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

相关文章

03 数仓平台 Kafka

kafka概述 定义 Kafka 是一个开源的分布式事件流平台(Event Streaming Plantform),主要用于大数据实时领域。本质上是一个分布式的基于发布/订阅模式的消息队列(Message Queue)。 消息队列 在大数据场景中主要采用…

电压驻波比

电压驻波比 关于IF端口的电压驻波比 一个信号变频后,从中频端口输出,它的输出跟输入是互异的。这个电压柱波比反映了它输出的能量有多少可以真正的输送到后端连接的器件或者设备。

ffmpeg 任意文件读取漏洞/SSRF漏洞 (CVE-2016-1897/CVE-2016-1898)

漏洞描述 影响范围 FFmpeg 2.8.x < 2.8.5FFmpeg 2.7.x < 2.7.5FFmpeg 2.6.x < 2.6.7FFmpeg 2.5.x < 2.5.10 漏洞环境及利用 搭建docker环境 访问8080端口看到上传界面 由于vulhub并没有讲述该漏洞如何复现&#xff0c;我们需要进入环境查看源码 <?php if(!…

Motion Plan之轨迹生成笔记 (2)

Motion Plan之搜索算法笔记 Motion Plan之基于采样的路径规划算法笔记 Motion Plan之带动力学约束路径搜索 什么是基于优化的轨迹生成 Optimization-Based Trajectory Planning&#xff08;基于优化的轨迹规划&#xff09;是一种常用的方法&#xff0c;用于生成自动化系统&am…

【数值计算方法(黄明游)】函数插值与曲线拟合(二):Newton插值【理论到程序】

​ 文章目录 一、近似表达方式1. 插值&#xff08;Interpolation&#xff09;2. 拟合&#xff08;Fitting&#xff09;3. 投影&#xff08;Projection&#xff09; 二、Lagrange插值1. 拉格朗日插值方法2. Lagrange插值公式a. 线性插值&#xff08;n1&#xff09;b. 抛物插值&…

EM32DX-C2【C#】

1说明&#xff1a; 分布式io&#xff0c;CAN总线&#xff0c;C#上位机二次开发&#xff08;usb转CAN模块&#xff09; 2DI&#xff1a; 公共端是&#xff1a; 0V【GND】 X0~X15&#xff1a;自带24v 寄存器地址&#xff1a;0x6100-01 6100H DI输入寄存器 16-bit &#x…

【NI-RIO入门】Real Time(实时系统解释)

1.什么是实时系统&#xff1f; 实时系统可以非常精确可靠的执行需要特定时许要求的系统&#xff0c;对于许多工程项目来说&#xff0c;通用操作系统&#xff0c;例如WINDOWS等标准PC上运行测量和控制程序是无法精确控制计时的&#xff0c;这些系统很容易受用户的其他程序、图像…

MYSQL练题笔记-聚合函数-各赛事的用户注册率

一、题目相关内容 1&#xff09;相关的表 2&#xff09;题目 3&#xff09;帮助理解题目的示例&#xff0c;提供返回结果的格式 二、自己初步的理解 有两张不同左右的表&#xff0c;用户表和赛事注册表。然后解题。 1.各种赛事的用户注册百分率 各种赛事的意味着通过contes…

Python实现FA萤火虫优化算法优化卷积神经网络分类模型(CNN分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 萤火虫算法&#xff08;Fire-fly algorithm&#xff0c;FA&#xff09;由剑桥大学Yang于2009年提出 , …

数据结构学习笔记——广义表

目录 一、广义表的定义二、广义表的表头和表尾三、广义表的深度和长度四、广义表与二叉树&#xff08;一&#xff09;广义表表示二叉树&#xff08;二&#xff09;广义表表示二叉树的代码实现 一、广义表的定义 广义表是线性表的进一步推广&#xff0c;是由n&#xff08;n≥0&…

4.grid_sample理解与使用

pytorch中的grid_sample 文章目录 pytorch中的grid_samplegrid_samplegrid_sample函数原型实例 欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; grid_sample 直译为网格采样&#xff0c;给定一个mask patch&#xff0c;根据在目标图像上的…

C语言 操作符详解

C语言学习 目录 文章目录 前言 一、算术操作符 二、移位操作符 2.1 左移操作符 2.2 右移操作符 三、位操作符 3.1 按位与操作符 & 3.2 按位或操作符 | 3.3 按位异或操作符 ^ 四、赋值操作符 五、单目操作符 5.1 逻辑反操作符&#xff01; 5.2 正值、负值-操作符 5.3 取地址…