简介

微博和witter都是现在习以为常的一款软件,深受大众喜爱,所以假期无聊就自己模仿写了一个简易版的推特项目。运行环境:python3.7+bottle框架+redis
该项目是采用python的bottle框架+redis实现的简单克隆witter系统,在设计上也切合MVC思想,实现了witter上收发动态,添加取消关注等大部分功能;适合初学者学习。

项目实体图

登录注册

首页

实时信息

用户个人

艾特功能

前端

前端写的十分的简单,基本上是几个简单的表单标签。然后加上几个修饰的CSS。
在登陆注册上也是采用了同一个页面

<div class="span-24"><div class="span-11 box"><form action="/signup" method="POST"><table><tr><td> 用户名:</td></tr><tr><td><input type="text" name="username" id="" style="width: 60%;"></td></tr><tr><td> 密码:</td></tr><tr><td> <input type="password" name="password" id="" style="width: 60%;"></td></tr><tr><td><button type="submit" style="width: 20%;">注册</button></td></tr></table></form></div><div class="span-11 box last"><form action="/login" method="POST"><table><tr><td> 用户名:</td></tr><tr><td><input type="text" name="username" id="" style="width: 60%;"></td></tr><tr><td> 密码:</td></tr><tr><td> <input type="password" name="password" id="" style="width: 60%;"></td></tr><tr><td><button type="submit" style="width: 20%;">登录</button></td></tr></table></form></div>
</div>

进入主页面之后就是几个DIV组合

<div class="span-24"><div class="span-16"><div id="updateform" class="box"><form action="/post" method="POST">{{username}},欢迎留言...<textarea name="content" id="" cols="70" rows="3"></textarea><br><input type="submit" value="发送"></form></div>% include('shared/post.tpl',posts=posts)</div><div class="span-7 last"><div class="box"><h4>粉丝数:{{followers_num}}</h4>% include('shared/userlist.tpl',users=followers)</div><div class="box"><h4>关注:{{following_num}}</h4>% include('shared/userlist.tpl',users=following)</div></div>
</div>

头部标签

<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>rewitter</title><link rel="stylesheet" href="/public/css/screen.css"><link rel="stylesheet" href="/public/css/custom.css"></head>
<body><div class="container"><div id="header" class="span-24"><div class="span-12"><br><h1>Rewitter</h1></div>% if defined('username'):<div class="span-12 last right-align"><br><br><a href="/">首页</a>|<a href="/mentions/{{username}}">@我</a>|<a href="/{{username}}">{{username}}</a>|<a href="/timeline">热聊</a>|<a href="/logout">退出</a></div>% end<hr></div>

其他的就不一一列出了,因为重点不在前端(前端也做的不太美观)。

后端核心代码

后端将函数对象进行了拆分和封装,从而降低耦合度。
将redis的连接单独抽取出来封装如下

import redis
REDIS_HOST='localhost'
REDIS_PORT='6379'
REDIS_DB=0r=redis.StrictRedis(host=REDIS_HOST,port=REDIS_PORT,db=REDIS_DB)

然后将功能代码进行了模板封装,这样使得在使用上更加的简洁方便,让代码整体性更强。

from __future__ import annotations
from typing import Optional
from conver import to_dict,to_list,to_set,to_string
import settings
import time
import rer=settings.rclass Timeline:@staticmethoddef posts(page=1,num=10) :start=(page-1)*numend=page*num-1posts_id=to_list(r.lrange('timeline',start,end))return [Post(pid) for pid in posts_id]class User:def __init__(self,id:int):self.id=int(id)user_data=to_dict(r.hgetall('user:{}'.format(self.id)))self.username=user_data['username']self.password=user_data['password']@staticmethoddef find_by_id(id:int) -> Optional[User]:if r.exists('user:{}'.format(int(id))):return User(int(id))return None@staticmethoddef find_by_username(username:str) -> Optional[User]:uid=r.hget('users',username)if uid:return User(int(uid))return None@staticmethoddef create(username:str,password:str) ->Optional[User]:uid=r.hget('users',username)if not uid:uid=r.incr('user:uid')udata={'username':username,'password':password}r.hmset('user:{}'.format(uid),udata)r.hset('users',username,uid)return User(int(uid))return None@staticmethoddef users():users=to_dict(r.hgetall('users'))return [User(uid) for username,uid in users.items()]# 获取帖子def posts(self) ->list[Post]:posts_id=to_list(r.lrange('user:{}:posts'.format(self.id ),0,9))return [Post(pid) for pid in posts_id]def timeline(self) ->list[Post]:posts_id=to_list(r.lrange('user:{}:timeline'.format(self.id ),0,9))return [Post(pid) for pid in posts_id]
# 粉丝def followers(self):followers=to_list(r.smembers('user:{}:followers'.format(self.id)))return [User(uid) for uid in followers]
# 关注def following(self):following=to_list(r.smembers('user:{}:following'.format(self.id)))return [User(uid) for uid in following]
# 粉丝数量def followers_num(self) ->int:return r.scard('user:{}:followers'.format(self.id))
# 关注数量def following_num(self) ->int:return r.scard('user:{}:following'.format(self.id))
# 判断关注    def isfollowing(self,user:User) ->bool:if self.id !=user.id:return r.sismember('user:{}:following'.format(self.id),user.id)return False
# 添加关注def add_following(self,user:User)->bool:if self.id !=user.id:r.sadd('user:{}:following'.format(self.id),user.id)r.sadd('user:{}:followers'.format(user.id),self.id)return Truereturn False
# 取消关注def re_following(self,user:User)->bool:if self.id !=user.id:r.srem('user:{}:following'.format(self.id),user.id)r.srem('user:{}:followers'.format(user.id),self.id)return Truereturn False
# @信息    def add_mention(self,pid:int):r.lpush('user:{}:mentions'.format(self.id),pid)
# @列表def mentions(self):posts_id=to_list(r.lrange('user:{}:mentions'.format(self.id),0,9))return [Post(pid) for pid in posts_id]class Post:def __init__(self,id:int):self.id=idpdata=to_dict(r.hgetall('post:{}'.format(self.id)))self.userid=pdata['userid']self.content=pdata['content']self.posttime=pdata['posttime']@staticmethoddef find_by_id(id:int) -> Optional[Post]:if r.sismember('post:id',int(id)):return Post(int(id))return None@staticmethoddef create(user:User,content:str) ->Post:pid=r.incr('post:uid')pdata={'userid':user.id,'content':content,'posttime':time.strftime("%Y-%M-%D %H:%M:%S",time.localtime())}r.hmset('post:{}'.format(pid),pdata)r.lpush('user:{}:timeline'.format(user.id),pid)r.lpush('user:{}:posts'.format(user.id),pid)r.lpush('timeline',pid)r.sadd('posts:id',pid)mentions=re.findall('@\w+',content)for mention in mentions:u=User.find_by_username(mention[1:])if u:u.add_mention(int(pid))return Post(int(pid))@propertydef username(self):return to_string( r.hget('user:{}'.format(self.userid),'username'))

接下来就是该项目的重点后端功能实现代码:

import bottle
import settings
import session
from conver import to_dict,to_list,to_set,to_string
import time
from model import User,Post,Timeliner=settings.r
# 获取登录信息
def islogin():sess=session.Session(bottle.request,bottle.response)if sess.is_new():return Falseelse:return User(sess['id'])
# 首页
@bottle.get('/')
@bottle.view('index')
def index():user=islogin()if user:res={'username':user.username,'posts':user.posts(),'followers':user.followers(),'following':user.following(),'followers_num':user.followers_num(),'following_num':user.following_num()}return reselse:bottle.redirect('/signup')
# 热聊
@bottle.get('/timeline')
@bottle.view('timeline')
def timeline():user=islogin()if user:res={'posts':Timeline.posts(),'users':User.users(),'username':user.username}return reselse:bottle.redirect('/')# 用户逻辑
@bottle.get('/<username>')
@bottle.view('profile')
def profile(username):login_user=islogin()user=User.find_by_username(username)if login_user and user:res={'username':user.username,'loginname':login_user.username,'followers':user.followers(),'following':user.following(),'followers_num':user.followers_num(),'following_num':user.following_num(),'posts':user.posts(),'isfollowing': login_user.isfollowing(user)}return resbottle.redirect('/')# 关注逻辑
@bottle.get('/<loginname>/following/<username>')
def following(loginname,username):login_user=User.find_by_username(loginname)user=User.find_by_username(username)if login_user and user:login_user.add_following(user)bottle.redirect('/{}'.format(user.username))else:bottle.redirect('/')# 取消关注
@bottle.get('/<loginname>/unfollowing/<username>')
def unfollowing(loginname,username):login_user=User.find_by_username(loginname)user=User.find_by_username(username)if login_user and user:login_user.re_following(user)bottle.redirect('/{}'.format(user.username))else:bottle.redirect('/')# 与我相关(@我)
@bottle.get('/mentions/<username>')
@bottle.view('mentions')
def mentions(username):login_user=islogin()user=User.find_by_username(username)if login_user and user:res={'loginname':login_user.username,'username':user.username,'isfollowing':login_user.isfollowing(user),'posts':user.mentions()}return resreturn bottle.redirect('/')# 注册失败返回
@bottle.get('/signup')
@bottle.view('signup')
def signup():return dict()# 注册
@bottle.post('/signup')
@bottle.view('signup')
def resiter():username= bottle.request.POST['username']password= bottle.request.POST['password']user=User.create(username,password)# uid=r.hget('users',username)if user:sess=session.Session(bottle.request,bottle.response)sess['id']=user.idsess.save()bottle.redirect('/')return dict()
# 登录
@bottle.post('/login')
@bottle.view('signup')
def login():username=bottle.request.POST['username']password=bottle.request.POST['password']user=User.find_by_username(username)# uid=r.hget('users',username).decode('utf-8')if user:#    upassword= r.hget('user:{}'.format(uid),'password').decode('utf-8')if user.password==password:sess=session.Session(bottle.request,bottle.response)sess['id']=user.idsess.save()bottle.redirect('/')            return dict()# 退出登录
@bottle.get('/logout')
def logout():sess=session.Session(bottle.request,bottle.response)sess.invalited()bottle.redirect('/')# 表单提交
@bottle.post('/post')
def post():user=islogin()if user:# 获取表单内容content=bottle.request.POST['content']Post.create(user,content)# 返回前端页面bottle.redirect('/')else:bottle.redirect('/signup')# 加载静态资源
@bottle.route('/public/<filename:path>')
def send_static(filename):return bottle.static_file(filename,root='public/')bottle.run(reloader=True)

以上就是该项目的功能实现,具体源码实现请参照下面链接。如有不足之处,请多指教,初学小白,希望大佬带带,哈哈哈。
源码链接

基于Python+redis实现的简单推特实现相关推荐

  1. Neo4j离线环境搭建与基于python中py2neo的简单操作

    Neo4j离线环境搭建与基于python中py2neo的简单操作 1 安装与配置 1.1 Neo4j安装 1.2 python操作环境配置 2 Neo4j操作 2.1 创建: 创建点 创建点边: 2. ...

  2. 基于Python + Redis实现分布式锁

    一.背景 为了保证一个方法或属性在高并发情况下的同一时间只能被同一个线程执行,在传统单体应用单机部署的情况下,可以使用并发处理相关的功能进行互斥控制. 但是,随着业务发展的需要,原单体单机部署的系统被 ...

  3. 基于python的图片数据集简单读取方法

    概述 最近在做和视觉深度学习有关的项目,在写相关代码的时候读取数据集的图片来进行预处理成了大问题.在查询了网上现有方法的基础上,总结了一种较为简单通用的读取方法. 遍历文件夹 首先是对于数据集文件夹的 ...

  4. 基于python LDA模型的英文推特邮件主题分析 完整数据+代码 可直接运行

    结果参考:https://www.bilibili.com/video/BV1jo4y1B7VQ/?spm_id_from=333.999.0.0&vd_source=8f3cf4ad6c08 ...

  5. 从头搭建一个基于 Python 的在线聊天室

    本场 Chat,是基于 Python + Redis + Flask 来搭建一个简单易用的在线聊天室.完全从零开始,一步一步完成整个项目. 主要分享内容: Flask 项目结构 Python Redi ...

  6. python appium自动化测试框架unittest_Appium基于Python unittest自动化测试 自动化测试框架 -- PO并生成html测试报告...

    基于python单元测试框架unittest完成appium自动化测试,生成基于html可视化测试报告 代码示例: #利用unittest并生成测试报告 class Appium_test(unitt ...

  7. python登录系统账号检测_一种基于python的惠普打印机默认用户名密码检测方法与流程...

    本发明涉及打印机检测技术领域,特别是一种基于python的惠普打印机默认用户名密码检测方法. 背景技术: 网络打印机是当前各大中小型企业正常办公比不可少的办公网络设备,但对于大中型企业而言,不同部门或 ...

  8. python评论情感分析nltk_基于 Python 和 NLTK 的推特情感分析

    基于 Python 和 NLTK 的推特情感分析 作者:宋彤彤 1. 导读 NLTK 是 Python 的一个自然语言处理模块,其中实现了朴素贝叶斯分类算法.这次 Mo 来教大家如何通过 python ...

  9. 【Mo 人工智能技术博客】基于 Python 和 NLTK 的推特情感分析

    基于 Python 和 NLTK 的推特情感分析 作者:宋彤彤 1. 导读 NLTK 是 Python 的一个自然语言处理模块,其中实现了朴素贝叶斯分类算法.这次 Mo 来教大家如何通过 python ...

最新文章

  1. 彻底搞懂视觉-惯性SLAM:基于VINS-Fusion(正式开课)
  2. 关于自动化网络监控的真相
  3. Selenium3自动化测试——14.操作Cookie
  4. CRC24循环冗余校验码的FPGA实现
  5. Java+XML+MVC框架StrutsCX简介[转]
  6. 【columnstore】mariadb columnstore 数据迁移
  7. 无限轮播图片的实现原理
  8. 自动化测试selenum
  9. 04Linux与Unix的关系
  10. pytorch1.0神经网络保存、提取、加载
  11. 写给数据小白:怎么让你的分析结论超出预期,不再是废纸一堆
  12. 我一个普通程序员,光靠GitHub打赏就年入70万,其实你也可以
  13. JAVA反射构建对象
  14. React项目本地环境正常显示,打包部署服务器图片不显示问题
  15. 五十一个经典小故事5
  16. 加拿大标准CAN/ULC-S102与美国标准ASTM E84 一样吗?
  17. iOS App上架遇到的错误(ERRORITMS-90096: )
  18. 测试工程师需掌握的技能
  19. GAIN: Missing Data Imputation using Generative Adversarial Nets学习笔记
  20. 开展跨境电商企业需要哪些资质?

热门文章

  1. makefile 中竖线 “|” 管道符的作用
  2. 循环单链表解决约瑟夫问题
  3. SQL语句中explain各字段含义
  4. S系列·删除文件夹的几种姿势
  5. 2021华为杯D题第四题完整代码
  6. 基于OkHttp访问网络时出现的网站证书认证问题
  7. RabbitMq应答模式、配置简介、常见阻塞场景
  8. 红帽linux配置yum源
  9. Word怎么批量删除空行和空格?有技巧很简单!
  10. 结对项目第一次作业——原型设计