美文网首页
6-通讯录

6-通讯录

作者: Double_Chen | 来源:发表于2018-11-08 15:24 被阅读7次

    实现通讯录功能,必须要经过下面这些步骤:

    • 用户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)
    

    GitHub链接

    相关文章

      网友评论

          本文标题:6-通讯录

          本文链接:https://www.haomeiwen.com/subject/baewxqtx.html