使用Redis构建简易社交网站(1)-创建用户与动态界面

目的

本文目的:实现简易社交网站中创建新用户和创建新动态功能。(完整代码附在文章末尾)

相关知识

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

redis基本命令

hget:从哈希中获取指定域的值。

conn = redis.Redis()
conn.hget("testhash", "field1")

执行结果:2

incr:将 key 中储存的数字值增一。

conn = redis.Redis()
conn.incr("testcount")

执行前:不存在 testcount 键。

执行后:

testcount 1

hset:将哈希中域 field 的值设为 value

conn = redis.Redis()
conn.hset("testhash", "field1", 2)
conn.hset("testhash", "field2", 4)

执行前:

{'field1': '1'}

执行后:

{'field1': '2', 'field2': '4'}

hmset:同时将多个域-值对设置到哈希表中。

conn = redis.Redis()
conn.hmset("test_hash", {
'id': 1,
'name': 'educoder',
'age': 2,
})

执行后:

{'age': '2', 'id': '1', 'name': 'educoder'}

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

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

执行前:

{'field1': '1'}

执行后:

{'field1': '2'}

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基本命令

将字符串全小写化:

'Hello, Educoder'.lower()

执行结果:'hello, educoder'

返回当前时间的时间戳。

time.time()

使用格式化拼接字符串:

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

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

实战例题:

编写 create_user(login_name, real_name) 函数,实现创建新用户的功能,具体参数与要求如下:

  • 方法参数login_name为用户登录名,real_name为用户真名;
  • 用户登录名预处理的实现:将用户登录名转换成全小写格式;
  • 重名检测的实现:查询哈希键users中是否存在与用户登录名同名的域,若存在,则不允许重新创建该用户,返回None
  • 分配用户编号的实现:对计数器user:id递增1,并将递增后的值作为新用户的编号;
  • 存储用户信息的实现:使用事务一次性提交:
    • 存储登录名的实现:将用户登录名记录到哈希键users当中,值为该用户编号;
    • 存储详情的实现:按照如下示意将用户信息存储到哈希键user:{id}中:

  • 返回创建结果的实现:返回新创建用户的编号。

编写 create_post(uid, content) 函数,实现创建新动态的功能,具体参数与要求如下:

  • 方法参数uid为发布动态的用户编号,content为要发布的动态内容;
  • 用户合法性检测的实现:查找用户编号对应详情信息哈希user:{uid}是否存在login_name域,若存在,则记录,若不存在,则不允许创建新动态,返回None
  • 分配动态编号的实现:对计数器post:id递增1,并将递增后的值作为新动态的编号;
  • 存储动态信息的实现:按照如下示意将动态信息存储到哈希键post:{id}中:

  • 更新用户动态数的实现:为该用户编号对应的详情信息哈希user:{uid}中的posts域的值加1
  • 返回创建结果的实现:返回新创建动态的编号。

 code.py

#code.py
#-*- coding:utf-8 -*-

import re
import time
import redis

conn = redis.Redis()

# 创建新用户
def create_user(login_name, real_name):
    # 请在下面完成要求的功能
    #********* Begin *********#
    login_name = login_name.lower()
    if conn.hget("users", login_name):
        return None

    uid = 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
    #********* End *********#

# 为用户创建新动态
def create_post(uid, content):
    # 请在下面完成要求的功能
    #********* Begin *********#
    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 None

    pipe.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
    #********* End *********#

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()
        break
    except redis.exceptions.ConnectionError:
        os.system("redis-server > /dev/null 2>&1 &")
        retry_time += 1
        if retry_time > 3:
            break

pipe = conn.pipeline(True)
pipe.delete("users", "user:id", "post:id")
keys = conn.keys("user:*") + conn.keys("post:*")
for key in keys:
    pipe.delete(key)
pipe.execute()

print "测试 create_user 方法..."
print "第一次创建登录名为 TestUser 的用户"
result1 = create_user('TestUser', 'Test User')
print "创建的用户ID为: " + str(result1)
print "当前分配的用户ID为: " + conn.get("user:id")
user_info = conn.hgetall("user:%i"%(result1))
user_info.pop("last_signup", "404")
print "创建的用户信息为: " + str(user_info)
print

print "第二次创建登录名为 TestUser 的用户"
result2 = create_user('TestUser', 'Test User2')
print "创建的用户ID为: " + str(result2)
print "当前分配的用户ID为: " + conn.get("user:id")
print

print "测试 create_post 方法..."
print "为用户 1 创建一条动态"
pid = create_post(1, "First POST!")
print "创建的动态ID为: " + str(pid)
print "当前分配的动态ID为: " + conn.get("post:id")
post_info = conn.hgetall("post:%i"%(pid))
post_info.pop("posted", "404")
print "创建的动态信息为: " + str(post_info)
user_info = conn.hgetall("user:1")
user_info.pop("last_signup", "404")
print "对应用户信息中更新为: " + str(user_info)
print

print "为不存在的用户 9 创建一条动态"
pid2 = create_post(9, "Illegal POST!")
print "创建的动态ID为: " + str(pid2)

pipe.delete("users", "user:id", "post:id")
keys = conn.keys("user:*") + conn.keys("post:*")
for key in keys:
    pipe.delete(key)
pipe.execute()

测试输入:无;

预期输出:

测试 create_user 方法...
第一次创建登录名为 TestUser 的用户
创建的用户ID为: 1
当前分配的用户ID为: 1
创建的用户信息为: {'login_name': 'testuser', 'posts': '0', 'real_name': 'Test User', 'followers': '0', 'following': '0', 'id': '1'}

第二次创建登录名为 TestUser 的用户
创建的用户ID为: None
当前分配的用户ID为: 1

测试 create_post 方法...
为用户 1 创建一条动态
创建的动态ID为: 1
当前分配的动态ID为: 1
创建的动态信息为: {'content': 'First POST!', 'uid': '1', 'user_name': 'testuser', 'id': '1'}
对应用户信息中更新为: {'login_name': 'testuser', 'posts': '1', 'real_name': 'Test User', 'followers': '0', 'following': '0', 'id': '1'}

为不存在的用户 9 创建一条动态
创建的动态ID为: None

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vitepress的使用

创建项目并启动项目 // 1.创建项目,直接在空项目下安装vitepress(npm/yarn等都可以,这个可以看官网,官网给了好几种安装方式) yarn add -D vitepress // 2.初始化配置项目(npm/官网也给了多种包管理工具的安装方式) npx vitepress init // 初始化命令执行完会遇到以下几个问题…

Python---函数递归---练习:猴子吃桃问题(本文以递归算法 解法为主)

相关链接:Python---函数递归---练习:斐波那契数列(本文以递归算法为主)-CSDN博客 案例:猴子吃桃问题 猴子吃桃问题。猴子第1天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。…

Web前端监控的方案

Web前端监控的方案 前端监控是一个非常重要的话题,对于业务的发展意义重大,就像遍布在城市各处的探头,实时监测整座城市的运行状况,保证系统的稳定、高效运行。 前端监控的意义 前端监控,对于业务和团队的重要性&am…

Kafka 的起源和背景

Apache Kafka 是一个分布式流处理平台,被广泛用于构建实时数据流应用程序和大数据处理系统。本文将深入探讨 Kafka 的起源、设计原则以及它在大数据领域中的重要作用。 大数据和实时数据处理背景 在大数据时代,处理海量数据和实时数据成为了一项关键挑…

C++学习之路(十七)C++ 用Qt5实现一个工具箱(增加托盘图标并且增加显示和退出菜单)- 示例代码拆分讲解

上篇文章,我们用 Qt5 实现了在小工具箱中添加了《为屏幕颜色提取功能增加一个点击复制的功能》功能。今天我们增加一个比较正式点的功能,就是增加托盘图标并且增加显示和退出菜单(越来越像回事了吧 😁 )。下面我们就来…

Python---函数递归---练习:使用递归求N的阶乘(如n=100)(本文以递归算法 解法为主)

相关链接:Python---函数递归---练习:斐波那契数列(本文以递归算法为主)-CSDN博客 Python---if选择判断结构、嵌套结构(if elif else)_python多重if嵌套-CSDN博客 案例:使用递归求N的阶乘&…

RabbitMQ架构是什么样的

publisher 生产者,发送消息的一方。 consumer 消费者,消费消息的一方。 queue 队列,存储消息。生产者投递的消息会暂存在消息队列中,等待消费者处理。 exchange 交换机,负责消息路由,生产者发送的消息由交换…

ORA-00257: archiver error. Connect internal only, until freed……

今天给客户测 试问题,让客户把数据发过来了。解压缩后一看,他们还是用的oracle 815版本的(他们exp导出时,带了导出日志,从导出日志中看出来是oracle 815版本的),不过没有关系,低版本的exp是可以用高版本的i…

C语言扫雷小游戏

以下是一个简单的C语言扫雷小游戏的示例代码&#xff1a; #include <stdio.h>#include <stdlib.h>#include <time.h>#define BOARD_SIZE 10#define NUM_MINES 10int main() { int board[BOARD_SIZE][BOARD_SIZE]; int num_flags, num_clicks; int …

vmware虚拟机17 安装macos14过程及问题处理亲测

前期准备 1、可引导可虚拟机安装的macOS Sonoma 14 ISO镜像安装文件 我找到得地址&#xff0c;下载自行解决啦 2、VMware虚拟机应用软件 官网下载就好&#xff0c;搜个码搞定 3、解锁工具macOS Unlocker 开始安装&#xff1a; 1、打开VMware软件&#xff0c;新建一个系统…

Sakila数据库和World数据库

Sakila数据库和World数据库 安装MySQL8.2的时候多出两个样例数据库 Sakila数据库和World数据库 Sakila数据库是一个关于DVD租赁的样例数据库&#xff0c;用于展示MySQL的各种功能和特性。Sakila数据库中包含了多个表&#xff0c;包括电影、演员、客户、租赁记录等&#xff0c;可…

AR助推制造业智能转型:实时远程协作与可视化引领生产创新

制造商面临着多方面的变革&#xff0c;技术的兴起催生了工业物联网&#xff08;IIoT&#xff09;&#xff0c;改变了现代工厂的外貌、系统和流程。同时&#xff0c;全球竞争压力和不断变化的员工队伍要求采用新的员工培训方法&#xff0c;并重新审视工人在工厂中的角色。尽管如…

GPT实现开放式世界游戏实践【生化危机】

最近开始研究如何基于GPT构建一个游戏引擎&#xff0c;于是先从简单的文字游戏开始探索。 从最简单的选择机制、故事机制&#xff0c;完善成一个包括天气、事件、技能、属性、伙伴、建造系统的-生化危机版文字游戏-。 我唯一的体验是&#xff1a;AI游戏&#xff0c;大有可为! …

c++——取地址(引用)和取内容(解引用)操作

今天又做蒙了一道题&#xff0c;把思考和实验记录下来。 struct sk{ int a; float b;}data; int *p; 若要使p指向data中的a域&#xff0c;正确的赋值语句是 p&a; pdata.a; p&data.a; *pdata.a前两个可以很容易看出错误之处&#xff0c;a是结构体内的变量&#xff0c;需…

MyBatis增删改查和配置文件

MyBatis增删改查 MyBatis新增 新增用户 持久层接口添加方法 void add(User user);映射文件添加标签 <insert id"add" parameterType"com.mybatis.pojo.User">insert into user(username,sex,address) values(# {username},# {sex},# {address}) <…

(一)舒尔特表练习记

舒尔特表练习记 1 练习的开始 我们知道&#xff0c;一段时间中注意力的保持&#xff0c;对于学习效果的影响很大。我想应该不少朋友们有过和我相似的感觉&#xff0c;学着学着&#xff0c;就莫名开始容易走神&#xff1b;一行字看过去&#xff0c;发现自己脑子里什么也没有留…

C++实现ATM取款机

C实现ATM取款机 代码&#xff1a;https://mbd.pub/o/bread/ZZeZk5Zp 1.任务描述 要求&#xff1a;设计一个程序&#xff0c;当输入给定的卡号和密码&#xff08;初始卡号和密码为123456) 时&#xff0c;系统 能登录 ATM 取款机系统&#xff0c;用户可以按照以下规则进行: 查询…

JVM垃圾回收机制GC

一句话介绍GC&#xff1a; 自动释放不再使用的内存 一、判断对象是否能回收 思路一&#xff1a;引用计数 给这个对象里安排一个计数器&#xff0c; 每次有引用指向它&#xff0c; 就把计数器1&#xff0c; 每次引用被销毁&#xff0c;计数器-1&#xff0c;当计数器为0的时候…

java消息中间件简介

一、为什么要使用消息中间件 消息中间件就是可以省去繁琐的步骤&#xff0c;直达目的&#xff0c;怎么讲呢&#xff0c;就是比如你想很多人&#xff0c;知道你的动态&#xff0c;而知道的人可能手机没电&#xff0c;可能手机信号不好&#xff0c;可能手机不在服务区&#xff0c…

指针常量和常量指针的区别

文章目录 指针常量常量指针即是指针常量又是常量指针 指针常量 指针常量的本质是常量&#xff0c;表示的是 这个指针所指向的地址不能发生改变。即指针变量的值&#xff08;即地址值&#xff09;不能发生修改。但是指针所指向的那块内存里的值是可以修改的。 注意&#xff1a;…