实现通讯录功能,必须要经过下面这些步骤:
- 用户A搜索用户B
- A向B发送好友申请
- B查看自己的好友申请列表
- B同意A的好友申请
- B/A查看自己的好友列表,即通讯录
在上面的过程中,搜索用户的功能因为我们已经有用户表了,所以可以直接拿来用,那么我们还需要建立两个表,好友请求表(friend_request)和好友绑定表(friend_bind),
好友请求表
class Friend_Request(db.Model):
__tablename__ = 'friend_request'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
create_time = db.Column(db.DateTime, default=datetime.now)
sender_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 发送者
target_id = db.Column(db.Integer, nullable=False) # 发送对象
state = db.Column(db.Integer, default=0) # 状态 0:等待通过 1:通过请求 2:被拒绝 3:已失效
sender = db.relationship('User', backref=db.backref('friend_requests')) # 反向关联
好友绑定表
class Friend_Bind(db.Model):
__tablename__ = 'friend_bind'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
create_time = db.Column(db.DateTime, default=datetime.now)
# 两个用户的id
uid = db.Column(db.Integer, nullable=False)
fid = db.Column(db.Integer, nullable=False)
因为有SQLAlchemy的ORM(对象关系映射),所以我们可以通过这样的方式建表,而不需要写sql指令,方便得多,
在这里普及一下db.relationship,假设有user和book两个表,
class User(db.Model):
...
class Book(db.Model):
...
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User',backref=db.backref('books'))
这种写法可以实现 book.user 来访问user对象,然后backref实现了反向关联,即可以通过任意一个 user.books 来获取Book表内所有user等于他的数据,是很方便的功能。
现在写完表后,记得执行脚本命令更新数据库
python3 manage.py db migrate
python3 manage.py db upgrade
回到app.py,写接口,首先是查找用户,在搜索框不填写默认是全部用户
查找用户
这里别忘了要导入sqlalchemy库的or_函数
@app.route('/search/', methods=['GET', 'POST'])
def search():
keyword = request.form.get('search')
like = '%%%s%%' % (keyword)
id_like = int(keyword)
users = User.query.filter(or_(User.username.like(like),User.id.like(id_like))).all()
result = {
'users': users
}
return render_template('search_users.html', **result)
再解释一下上面的代码吧,
@app.route('...')声明了一个接口路径,并且只允许接受GET和POST请求,当外界访问这个路径时调用search函数,将请求参数用于做数据库表的查询,我们可以通过用户名或者用户id作为关键字来查询所有相关的user用户,然后返回给前端页面,记得render_template是返回前端页面的,如果希望返回json数据给移动端,可以用jsonify函数。
发送好友申请
接下来是发送好友申请,好友申请发送后,会在数据库内插入一条数据,等待对方拉取数据处理,好友申请一般情况下是不能重复发送的,那就多做一层判断
@app.route('/friend_request/', methods=['POST'])
@login_required
def friend_request():
if request.method == 'POST':
target_id = request.form.get('target_id')
user_id = session.get('user_id')
exist = Friend_Request.query.filter(Friend_Request.sender_id == user_id,
Friend_Request.receiver_id == target_id).first()
if exist:
return u'不能重复发送请求'
target = User.query.filter(User.id == target_id).first()
if target:
fr = Friend_Request(receiver_id=target.id)
user = User.query.filter(User.id == user_id).first()
fr.sender = user
fr.sender_id = user.id
fr.state = 0
db.session.add(fr)
db.session.commit()
return u'申请添加好友成功'
好友请求列表
好友请求列表的入口放在通讯录里面,进去之后可以获取所有对我的申请
@app.route('/friend_request_list/')
@login_required
def friend_request_list():
user_id = session.get('user_id')
friendRs = Friend_Request.query.filter(Friend_Request.target_id == user_id,
Friend_Request.state == 0).all()
result = {
'requests': friendRs
}
return render_template('friend_request_list.html', **result)
同意好友请求
同意好友请求之后将状态设为已通过,并且将用户数据插入到好友绑定表当中,为了方便查询,将两个用户的id值做大小排序处理再插入
@app.route('/agree_friend_request/<sender_id>')
@login_required
def agree_friend_request(sender_id):
print(sender_id)
user_id = str(session.get('user_id'))
fr = Friend_Request.query.filter(Friend_Request.sender_id == sender_id,
Friend_Request.target_id == user_id).first()
if fr == None:
return u'好友请求出现错误'
fr.state = 1 # 设为通过状态
# 让user1 < user2,方便处理
uid = min(user_id,sender_id)
fid = max(user_id,sender_id)
exist = Friend_Bind.query.filter(Friend_Bind.uid==uid,
Friend_Bind.fid==fid).first()
if exist is not None:
db.session.commit()
return u'用户之间已经是好友,无法重复绑定'
friend = Friend_Bind(uid=uid,fid=fid)
db.session.add(friend)
db.session.commit()
return u'已同意该好友请求'
好友列表
现在我们完成了添加好友所需要的功能,现在只要从数据库里面查找数据,将好友列表展示出来就行了
在用户绑定表里,将uid或者fid等于user_id的数据取出来
@app.route('/address_list/')
@login_required
def address_list():
user_id = session.get('user_id')
binds = Friend_Bind.query.filter(or_(Friend_Bind.uid == user_id, Friend_Bind.fid == user_id)).all()
friends = []
for bind in binds:
nid = None
if bind.uid == user_id:
nid = bind.fid
else:
nid = bind.uid
friend = User.query.filter(User.id == nid).first()
friends.append(friend)
context = {'friends': friends}
return render_template('address_list.html',**context)
网友评论