Exemplo n.º 1
0
def rewind_last_swipe(uid):
    '''反悔上一次滑动 (每天允许反悔 3 次,反悔的记录只能是五分钟之内的)'''
    now = datetime.datetime.now()

    # 检查今天是否已经反悔 3 次
    rewind_key = keys.REWIND_TIMES_K % (now.date(), uid)
    rewind_times = rds.get(rewind_key, 0)
    if rewind_times >= config.REWIND_TIMES:
        raise errors.RewindLimit

    # 找到最后一次的滑动
    # select * from swiped where uid=1001 order by stime desc limit 1;
    last_swipe = Swiped.objects.filter(uid=uid).latest('stime')

    # 检查最后一次滑动是否在 5 分钟内
    time_past = (now - last_swipe.stime).total_seconds()
    if time_past >= config.REWIND_TIMEOUT:
        raise errors.RewindTimeout

    with atomic():  # 将多次数据修改在事务中执行
        if last_swipe.stype in ['like', 'superlike']:
            # 如果之前匹配成了好友,则删除好友关系
            Friend.breakoff(uid, last_swipe.sid)

            # 如果上一次是超级喜欢,则从对方的优先推荐队列中删除自己的 UID
            if last_swipe.stype == 'superlike':
                rds.lrem(keys.FIRST_RCMD_Q % last_swipe.sid, 0, uid)

        # 删除最后一次的滑动
        last_swipe.delete()

        # 今日反悔次数加一
        rds.set(rewind_key, rewind_times + 1, 86460)  # 缓存过期时间为一天零60秒
Exemplo n.º 2
0
def rewind_last_swipe(uid):
    '''反悔上一次滑动 (每天允许反悔 3 次, 反悔的记录只能是五分钟之内的)'''
    now = datetime.datetime.now()

    # 检查今天是否已经反悔 3 次
    rewind_key = keys.REWIND_TIMES_K % (now.date(), uid)
    rewind_times = rds.get(rewind_key, 0)
    if rewind_times >= config.REWIND_TIMES:
        raise errors.RewindLimit

    # 找到最后一次滑动
    last_swipe = Swiped.objects.filter(uid=uid).latest('stime')

    # 检查最后一次滑动是否在 5 分钟之内
    time_past = (now - last_swipe.stime).total_seconds()
    if time_past >= config.REWIND_TIMEOUT:
        raise errors.RewindTimeout

    with atomic():  # 将多次数据修改在事务中执行
        if last_swipe.stype in ['like', 'superlike']:
            # 如果之前匹配成了好友,则删除好友关系
            Friend.breakoff(uid, last_swipe.sid)
            # 如果上一次是超级喜欢,则删除优先推荐队列中的数据
            if last_swipe.stype == 'superlike':
                rds.lrem(keys.FIRST_RCMD_Q % last_swipe.sid, 0, uid)

        # 撤销被滑动者改变的积分
        score = config.SWIPE_SCORE[last_swipe.stype]
        rds.zincrby(keys.HOT_RANK, -score, last_swipe.sid)

        # 删除最后一次的滑动
        last_swipe.delete()

        # 今日反悔次数加一
        rds.set(rewind_key, rewind_times + 1, 86460)  # 缓存过期时间为一天零60秒
Exemplo n.º 3
0
def rewind_swipered(user):
    '''反悔一次滑动记录'''

    # 获取今天的反悔次数
    rewind_times = rds.get(keys.REWIND_KEY % user.id, 0)
    # 检查今天返回是否达到了反悔上限
    if rewind_times >= cfg.DAILY_REWIND:
        raise stat.RewindLimit
    # 找到最近的一次滑动记录
    latest_swiped = Swiped.objects.filter(uid=user.id).latest('stime')
    # 检查反悔的记录是否是五分钟之内的
    now = datetime.datetime.now()
    if (now - latest_swiped.stime).total_seconds() >= cfg.REWIND_TIMEOUT:
        raise stat.RewindTimeout
    # 检查上一次滑动是否有可能匹配了好友关系
    if latest_swiped.stype in ['like', 'superlike']:
        # 删除好友关系
        Friend.break_off(user.id, latest_swiped.sid)

        # 如果上一次是超级喜欢 将自身的uid从对方的优先推荐队列里面删除
        if latest_swiped.stype == 'superlike':
            rds.zrem(keys.SUPERLIKED_KEY % latest_swiped.sid, user.id)

    # 删除滑动记录
    latest_swiped.delete()
    # 更新当天的滑动词数,同时设置过期时间到下一个凌晨
    next_zero = datetime.datetime(now.year, now.month,
                                  now.day) + datetime.timedelta(1)
    remain_seconds = (next_zero - now).total_seconds()
    rds.set(keys.REWIND_KEY % user.id, rewind_times + 1, int(remain_seconds))
Exemplo n.º 4
0
def send_sms(mobile):
    '''发送短信验证码'''
    key = keys.VCODE_K % mobile

    # 检查短信发送状态,防止短时间内给用户重复发送短信
    if rds.get(key):
        return True  # 之前发送过验证码,直接返回 True

    vcode = gen_rand_code()  # 产生验证码
    inf_log.debug('验证码: %s' % vcode)

    args = conf.YZX_SMS_ARGS.copy()  # 原型模式
    args["param"] = vcode
    args["mobile"] = mobile

    response = requests.post(conf.YZX_SMS_API, json=args)
    if response.status_code == 200:
        result = response.json()
        inf_log.debug('短信发送状态: %s' % result.get('msg'))
        if result.get('code') == '000000':
            rds.set(key, vcode, 600)
            return True
        else:
            return False
    return False
Exemplo n.º 5
0
def submit_code(request):
    phonenum = request.POST.get('phonenum')
    vcode = request.POST.get('vcode')

    # 检查验证码是否正确
    key = keys.VCODE_K % phonenum
    cache_code = rds.get(key)

    # 验证码正确时...
    if vcode and vcode == cache_code:
        user_num = User.objects.filter(phonenum=phonenum).count()
        # 如果验证码正确并且已有帐号时...
        if user_num == 1:
            user = User.objects.filter(phonenum=phonenum)[0]
            inf_log.info(f'User Login:{user.id}/{user.phonenum}')

            request.session['uid'] = user.id

            return render_json(data=user.to_dict())

        # 如果验证码正确 没有帐号时...
        elif user_num == 0:
            # 添加 用户
            user = User.objects.create(phonenum=phonenum, nickname=phonenum)
            # 添加 用户资料
            profile = Profile.objects.create(id=user.id)
            # 日志
            inf_log.info(f'User Register:{user.id}/{user.phonenum}')
            # 设置session
            request.session['uid'] = user.id

            return render_json(data=user.to_dict())
    # 验证码错误时...
    else:
        raise errors.VcodeErr('验证码错误')
Exemplo n.º 6
0
def rewind_swiper(uid):
    """
    反悔一次滑动
    每天允许反悔3次,反悔记录只能是5分子之内的
    """
    now = datetime.datetime.now()  # 取出当前时间
    # 取出当天的反悔次数
    rewind_k = keys.REWIND_k % (now.date(), uid)
    rewind_times = rds.get(rewind_k, 0)  # 取出当天反悔次数 取不到的时候默认为0
    # 检查当前反悔次数
    if rewind_times >= config.REWIND_TIMES:
        raise stat.RewindLimit

    # 取出最后一次滑动记录
    latest_swipe = Swiped.objects.filter(uid=uid).latest('time')
    # 检查滑动记录时间是否超过5分钟
    pass_time = now - latest_swipe.time
    if pass_time.total_seconds() >= config.REWIND_TIMEOUT:
        raise stat.RewindTimeout

    # 如果是超级喜欢,需要将自己从对方的优先队列中删除
    # 如果之前是喜欢或者超级喜欢,需要撤销好友关系
    if latest_swipe.stype == 'superlike':
        rds.lrem(keys.FIRST_RCMD_K % latest_swipe.sid, 1, uid)
        Friend.break_off(uid, latest_swipe.sid)
    elif latest_swipe.stype == 'like':
        Friend.break_off(uid, latest_swipe.sid)

    # 删除滑动记录
    latest_swipe.delete()
    # 更新反悔次数
    rds.set(rewind_k, rewind_times + 1, 86400)
Exemplo n.º 7
0
def get_or_create(cls, defaults=None, **kwargs):
    """
    Look up an object with the given kwargs, creating one if necessary.
    Return a tuple of (object, created), where created is a boolean
    specifying whether an object was created.
    """
    # 检查参数中是否有 主键
    if 'id' in kwargs or 'pk' in kwargs:
        # 创建缓存 key
        pk = kwargs.get('id') or kwargs.get('pk')
        model_key = MODEL_KEY % (cls.__name__, pk)

        # 先从缓存获取数据
        model_obj = rds.get(model_key)
        if model_obj is not None and isinstance(model_obj, cls):
            return model_obj, False

    # 缓存中未取到,直接从数据库获取
    model_obj, created = cls.objects.get_or_create(defaults, **kwargs)

    # 将数据库取出的数据写入缓存
    model_key = MODEL_KEY % (cls.__name__, model_obj.pk)
    rds.set(model_key, model_obj, ex=86400 * 7)  # 设置缓存过期时间为 一周

    return model_obj, created
Exemplo n.º 8
0
def rewind_last_swiped(user_id):
    ''' 撤销最后⼀次滑动,每天允许反悔三次,反悔时间距上一次滑动时间不超过5分钟'''
    now = datetime.datetime.now()
    rewind_key = keys.REWIND_TIMES_K % (now.date(), user_id)
    # 1检查今天的反悔次数是否超过三次
    rewind_times = rds.get(rewind_key, 0)
    if rewind_times > config.REWIND_TIMES:
        raise errors.RewindLimit()

    # 2找到最后一次滑动
    last_swpied = Swiped.objects.filter(user_id=user_id).latest('stime')

    # 3检查最后一次滑动时间距离现在是否在5分钟内
    past_time = (now - last_swpied.stime).total_seconds()
    if past_time > config.REWIND_TIMEOUT:
        raise errors.RewindTimeout()

    with atomic():
        # 4删除好友关系(只要上一次滑动类型是喜欢或超级喜欢,都有可能匹配为好友)
        if last_swpied.stype in ['like', 'superlike']:
            Friend.remove_relation(user_id, last_swpied.sid)
            # 5如果最后一次滑动是超级喜欢删除自己在对方的优先推荐列表
            if last_swpied.stype == 'superlike':
                rds.lrem(keys.PRIOR_RCMD_LIST % last_swpied.sid, value=user_id)

        # 6删除滑动记录
        last_swpied.delete()
        # 今日反悔次数加一
        rds.set(rewind_key, rewind_times + 1, 86500)  # 缓存过期时间为一天零100秒
        '''撤回最后一次滑动所改变的对方的积分,'''
        rds.zincrby(keys.HOT_RANK, last_swpied.sid,
                    -config.RANK_SCORE[last_swpied.stype])
Exemplo n.º 9
0
def get_profile(request):
    '''获取用户配置'''
    key = keys.MODEL_K % (Profile.__name__, request.uid)
    profile = rds.get(key)  # 先从缓存获取数据
    if profile is None:
        profile, _ = Profile.objects.get_or_create(id=request.uid)  # 缓存中没有,直接从数据库获取
        rds.set(key, profile)  # 将 profile 存入缓存
    return render_json(profile.to_dict())
Exemplo n.º 10
0
def get_profile(request):
    '''获取个人资料'''

    key = keys.PROFILE_KEY % request.uid
    result = rds.get(key)
    print('从缓存获取:%s' % result)
    if result is None:
        profile, _ = Profile.objects.get_or_create(id=request.uid)
        result = profile.to_dict()
        rds.set(key, result, 1000)  # 将数据写入到缓存中

    return render_json(result)
Exemplo n.º 11
0
def get_profile(request: HttpRequest):
    '''获取用户资料'''
    # request对象,新增user属性
    # 考虑性能问题:request.user.profile都是需要从磁盘中进行读取
    key = keys.PROFILE_KEY % request.user.id
    profile_data = rds.get(key)
    if profile_data is None:
        # 缓存与数据库的操作
        profile_data = request.user.profile.to_dict()
        # 将取出的数据添加至缓存
        rds.set(key, profile_data)
    return render_json(data=profile_data, code=OK)
Exemplo n.º 12
0
def send_code(phonenum):
    '''给用户发送验证码'''
    if not is_phonenum(phonenum):
        return False
    key = keys.VCODE_K + str(f'{phonenum}')

    if rds.get(key):
        return True
    vcode = make_code()
    info_log.debug(f'验证码:{phonenum}-{vcode}')
    rds.set(key, vcode, 600)
    return send_msg(phonenum, vcode)
Exemplo n.º 13
0
def get_profile(request):
    '''获取个人资料'''
    key = keys.PROFILE_KEY % request.user.id
    profile_data = rds.get(key)
    print('先从Redis缓存获取数据: %s' % profile_data)

    if profile_data is None:
        profile_data = request.user.profile.to_dict()
        print('缓存中没有,从数据库获取: %s' % profile_data)
        rds.set(key, profile_data)
        print('将取出的数据添加到缓存')
    return render_json(profile_data)
Exemplo n.º 14
0
def rewind_swipe(uid):
    '''
    反悔一次滑动

    每天允许反悔 5 次,反悔的记录只能是五分钟之内的
    '''
    now = datetime.datetime.now()  # 当前时间

    # 取出当天的反悔次数
    rewind_k = keys.REWIND_K % (now.date(), uid)
    rewind_times = rds.get(rewind_k, 0)  # 当天反悔次数,取不到时默认为 0
    # 检查当前反悔次数
    if rewind_times >= config.REWIND_TIMES:
        raise stat.RewindLimit

    # 取出最后一次的滑动记录
    latest_swipe = Swiped.objects.filter(uid=uid).latest('stime')
    # 检查滑动记录的时间否超是过 5 分钟
    pass_time = now - latest_swipe.stime
    if pass_time.total_seconds() > config.REWIND_TIMEOUT:
        raise stat.RewindTimeout

    # 如果是超级喜欢,需要将自己从对方优先推荐队列删除
    # 如果之前是喜欢或超级喜欢,需要撤销好友关系
    if latest_swipe.stype == 'superlike':
        rds.lrem(keys.FIRST_RCMD_K % latest_swipe.sid, 1, uid)
        Friend.break_off(uid, latest_swipe.sid)
    elif latest_swipe.stype == 'like':
        Friend.break_off(uid, latest_swipe.sid)

    # 调整对方的滑动积分
    score = config.HOT_RANK_SCORE[latest_swipe.stype]
    rds.zincrby(keys.HOT_RANK_K, -score, latest_swipe.sid)

    # 将滑动记录删除
    latest_swipe.delete()

    # 更新反悔次数
    rds.set(rewind_k, rewind_times + 1, 86400)
    return config.REWIND_TIMES, rds.get(rewind_k, 0)
Exemplo n.º 15
0
def rewind_last_slide(uid):
    '''返回上一次滑动(每天允许返回三次,返回的记录只能是五分钟以内的)'''
    now = datetime.datetime.now()
    # 检查今天是否已经反悔3次 ---> 适合缓存
    rewind_key = keys.REWIND_LIMIT_K % (now.date(), uid)  # now.date() 是日期
    rewind_limit = rds.get(rewind_key, 0)
    '''
        每日更新三次
        # 错误方式
        1.过期时间 
        2.定时任务 ---> 人数多了,异步任务太多处理不了 
        3.建立redis库 ---> 保存key,到时间清空,在清空的时候也会出现临界点问题
        # 正确方式
        将日期拼接在用户的key上面
        
        ※时间临界点:
            23:59:59.123 使用了2次反悔,现在要准备用第三次
            当用了之后时间变成 00:00:00.321了,此时变成了3
            用户一天都不能用返回了,这就是临界点可能出现的问题
    '''
    if rewind_limit >= config.REWIND_LIMIT:
        raise errors.RewindLimit

    # 找当最后一次的滑动
    # 对应的SQL语句 select * from slider where uid=1001 order by stime desc limit 1;
    last_slide = Slider.objects.filter(uid=uid).latest('stime')  # 不分对方和方向
    # latest() ---> 最新的(按照时间最新的),这个latest强调时间

    # 检查最后一次滑动是否在5分钟以内
    # (now - last_slide.stime)两个相减的值是datetime.timedelta(天,秒,毫秒),是一个特殊的对象
    # (now - last_slide.stime).seconds 忽略了天和毫秒,单位是秒
    # (now - last_slide.stime).total_seconds() 天秒毫秒全加起来,单位是秒
    time_past = (now - last_slide.stime).total_seconds()  # 已经过去的时间
    if time_past >= config.REWIND_TIMEOUT:
        raise errors.RewindTimeout

    with atomic():  # 将多次数据修改在事务中执行
        # 衍生的功能 +
        #          ↓
        # 1.如果之前匹配成了好友,则删除好友关系
        if last_slide.stype in ['like', 'superlike']:
            Friend.breakoff(uid, last_slide.sid)

            # 2.如果之前是超级喜欢,则找到对方的优先推荐队列把我的数据删除
            if last_slide.stype == 'superlike':
                rds.lrem(keys.FIRST_RCMD_Q % last_slide.sid, 0, uid)

        # 3.删除最后一次的滑动
        last_slide.delete()

        # 4.今日返回次数加一,缓存过期时间一天(86400秒),+ N秒 是为了避免时间临界点问题
        rds.set(rewind_key, rewind_limit + 1, 86400 + 1)
Exemplo n.º 16
0
def send_vcode(phonenum):
    if not is_phonenum(phonenum):
        return False

    key = keys.VCODE_K % phonenum
    if rds.get(key):
        return True

    # 产生验证码
    vcode = random_code()
    print('随机码:', vcode)
    inf_log.debug(f'验证码:{phonenum}-{vcode}')
    rds.set(key, vcode, 600)
Exemplo n.º 17
0
def show_profile(request):
    """查看个人资料"""
    uid = request.session['uid']
    key = keys.PROFILE_K % uid

    profile = rds.get(key)
    inf_log.debug(f'从数据库中获取数据:{profile}')

    if profile is None:
        profile, _ = Profile.objects.get_or_create(id=uid)
        inf_log.debug(f'从数据库中获取数据:{profile}')
        rds.set(key, profile)
        inf_log.debug('将数据写入到缓存')

    return render_json(profile.to_dict())
Exemplo n.º 18
0
def send_vcode(phone):
    if not is_phonenum(phone):
        return False

    key = keys.VCODE_K % phone
    # 检查缓存是否存在,防止在有效时间内频繁发送验证码
    if rds.get(key):
        return True

    # 手机号正确,发送验证码
    code = make_code(6)
    inf_log.debug(f'验证码:{phone}-{code}')
    # 设置缓存,设置验证码的有效时间
    rds.set(key, code, 600)
    return send_sms(phone, code)
Exemplo n.º 19
0
def show_profile(request):
    uid = request.session.get('uid')
    key = keys.PROFILE_K % uid

    # 先从缓存获取数据,没有就冲数据库获取,然后存在缓存里面
    profile = rds.get(key)
    inf_log.debug(f'从缓存中获取数据: {profile}')

    if profile is None:
        profile, _ = Profile.objects.get_or_create(id=uid)
        inf_log.debug(f'从数据库中获取数据: {profile}')
        rds.set(key, profile)
        inf_log.debug('将数据写入到缓存')


    return render_json(data=profile.to_dict())
Exemplo n.º 20
0
def rewind_swiped(user):
    '''
    1.获取反悔次数      ---存储位置
    2.返回一次滑动记录    ---              找到最近一次的滑动记录;[返回的记录只能为5min之内]
    3.每天允许反悔3次    ---               需要对当天返回次数进行记录;并作出检查确定哪一次是最近一次;
    4.返回记录只能是5min以内   ---          找到最近的滑动记录,检查反悔记录是否为5mins以内,判断当前时间与滑动时的时间操作;

    5.检查上一次滑动是否匹配为好友,如果是,则需要先删除好友记录;
    6.如果上一次是超级喜欢,将自身uid从对方的右滑推荐队列中删除

    7.删除滑动记录;     ---               需要更新滑动记录
    '''
    # 获取今天的反悔次数
    # 默认0次反悔次数,参数最好写入配置文件;
    rewind_times = rds.get(keys.REWWIND_KEY % user.id, 0)
    # 检查是否达到限制次数
    if rewind_times >= cfg.DAILY_REWIND:
        raise stat.RewindLimit
    # 根据时间找到最近的一次的滑动记录:filter的内容无顺序;
    # 取最近的一次滑动的方法:last(),latest()对比区别
    latest_swiped = Swiper.objects.filter(uid=user.id).latest('stime')
    # 检查返回记录在五分钟以内:当前时间与滑动时间的差值
    now = datetime.datetime.now()
    if (now - latest_swiped.stime).total_seconds() >= cfg.REWIND_TIMEOUT:
        raise stat.RewindTimeout

    # 检查上一次滑动是否匹配成好友
    if latest_swiped.stype in ['like', 'superlike']:
        # 如果是好友,删除好友关系
        Friend.break_off(user.id, latest_swiped.sid)
        # 如果上一次超级喜欢,将自身uid从对方的优先推荐队列中删除
        if latest_swiped.stype == 'superlike':
            rds.zrem(keys.SUPERLIKED_KEY % latest_swiped.sid, user.id)

    # 如果反悔的话,需要还原用户的滑动积分
    score = -cfg.SWIPE_SCORE[latest_swiped.stype]  # 查找反悔的滑动积分
    rds.zincrby(keys.HOT_RANK_KEY, score, latest_swiped.sid)
    # 删除滑动记录
    latest_swiped.delete()
    # 更新当天的滑动次数
    rds.set(keys.REWWIND_KEY % user.id, rewind_times + 1)
    # 更新过期过期时间(次日零点过期),需要计算过期时间,由于date在月末临界点,不够安全,采用timedelta()
    next_zero = datetime.datetime(now.year, now.month,
                                  now.day) + datetime.timedelta()
    remain_seconds = next_zero - now
    rds.set(keys.REWWIND_KEY % user.id, rewind_times + 1, remain_seconds)
Exemplo n.º 21
0
def get(self, *args, **kwargs):
    """自定义 get 方法处理缓存"""
    
    model_cls_name = self.model.__name__  # 模型的类名

    pk = kwargs.get('id') or kwargs.get('pk')
    if pk is not None:
        model_key = MODEL_K % (model_cls_name, pk)
        model_obj = rds.get(model_key)
        if isinstance(model_obj, self.model):
            return model_obj
    
    # 如果缓存里面找不到,再到数据库中查找,然后写入缓存
    model_obj = self._get(*args, **kwargs)
    model_key = MODEL_K % (model_cls_name, model_obj.pk)
    rds.set(model_key, model_obj)

    return model_obj
Exemplo n.º 22
0
def send_vcode(phonenum):
    '''给用户发送短信验证码'''
    # 验证手机号
    if not is_phonenum(phonenum):
        return False

    key = keys.VCODE_K % phonenum

    # 检查缓存中是否已有验证码,防止用户频繁调用接口
    if rds.get(key):
        return True

    # 产生验证码
    vcode = random_code()
    print('随机码:', vcode)
    rds.set(key, vcode, 600)  # 将验证码添加到缓存,并多设置一些时间

    return send_sms(phonenum, vcode)  # 向用户手机发送验证码
Exemplo n.º 23
0
def show_profile(request):
    '''查看个人资料、交友资料'''
    key = keys.USER_RPROFILE_K % request.uid

    # 先从缓存获取数据
    result = rds.get(key, {})
    inflog.debug('从缓存获取: %s' % result)

    # 判断 result 是否是空值,如果为空,则从数据库获取数据
    if not result:
        user = User.objects.get(id=request.uid)  # 从数据库获取 user
        result.update(user.to_dict())
        result.update(user.profile.to_dict())  # 从数据库获取 profile
        inflog.debug('从数据库获取: %s' % result)
        rds.set(key, result)  # 将结果保存到 缓存
        inflog.debug('将数据写入缓存')

    return render_json(result)
Exemplo n.º 24
0
def get(self, *args, **kwargs):
    '''带缓存处理的 objects.get() 方法'''
    # 从缓存获取数据
    pk = kwargs.get('pk') or kwargs.get('id')
    if pk is not None:
        key = MODEL_KEY % (self.model.__name__, pk)
        model_obj = rds.get(key)
        if isinstance(model_obj, self.model):
            return model_obj

    # 缓存中没有,从数据库获取
    model_obj = self._get(*args, **kwargs)

    # 将取出的数据写入缓存
    key = MODEL_KEY % (self.model.__name__, model_obj.pk)
    rds.set(key, model_obj)

    return model_obj
Exemplo n.º 25
0
def rewind_last_swipe(uid):
    '''
    反悔最后一次滑动的记录(确定逻辑顺序):
    :param uid: 用户的 ID
    :return:
    '''
    # 1.检查今天是否已经达到3次
    #   还需要拼接一个时间, 确保删除的次数是当天的, 避免时间跨界的问题
    now = datetime.datetime.now()
    key = 'Rewind-%s-%s' % (uid, now.date())
    # 取出当天反悔的次数, 默认为0
    rewind_times = rds.get(key, 0)
    if rewind_times >= 3:
        print('反悔次数达到限制')
        # 此时直接跳出去, 就不需要再进行后面的操作了
        raise stat.RewindLimited
        # return 1007  # TODO: 需要给前端反回状态码

    # 2.从数据库里面取出最后一次滑动的记录
    latest_swiped = Swiped.objects.filter(uid=uid).latest('stime')

    # 3.检查反悔记录是否是五分钟以内的
    past_time = now - latest_swiped.stime
    if past_time.seconds > 300:
        print('反悔超时')
        raise stat.RewindTimeout
        # return 1008  # TODO: 需要给前端反回状态码

    # 给下面操作数据库的代码添加事务:
    with atomic():
        # 4.检查上次滑动记录是否匹配成功, 如果匹配成功的话, 需要删除好友
        #       不管之前有没有, 都来一次删除, 强删的话是不会报错的
        if latest_swiped.stype in ['like', 'superlike']:
            Friend.break_off(uid, latest_swiped.sid)

        # 5.检查上次是否是超级喜欢, 如果是, 将自己的ID从对方的优先队列中删除
        if latest_swiped.stype == 'superlike':
            # 把对方优先队列中自己的记录给删除
            rds.lrem(keys.FIRST_RCMD_Q % latest_swiped.sid, 0, uid)
        # 6.删除滑动记录
        latest_swiped.delete()

        # 7. 累加当天反悔次数
        rds.set(key, rewind_times + 1)
Exemplo n.º 26
0
def get_profile(request):
    '''获取个人资料'''
    uid = request.GET.get('uid')
    if not uid:
        uid = request.uid
    key = keys.PROFILE_K % uid
    result = rds.get(key)
    print('从缓存获取: %s' % result)
    if result is None:
        profile, _ = Profile.objects.get_or_create(id=uid)
        user_info= User.objects.get(id=uid).to_dict()
        print(User.objects.get(id=uid).nickname)
        profile_info = profile.to_dict()
        result = {**user_info,**profile_info}
        print('从数据库获取: %s' % result)

        rds.set(key, result, 1000)  # 将数据写入缓存
        print('将数据写入缓存')
    return render_json(result)
Exemplo n.º 27
0
def rewind_last_swipe(uid):
    '''
    反悔最后一次的滑动

    - 每天允许反悔 3 次
    - 反悔的记录只能是五分钟之内的
    '''
    # 取出当前时间
    now = datetime.datetime.now()

    # 检查当前是否达到了 3 次
    key = keys.REWIND_K % (now.date(), uid)
    rewind_times = rds.get(key, 0)  # 取出当天的反悔次数,默认为 0 次
    if rewind_times >= 3:
        raise stat.RewindLimited  # 当天达到额定次数: 直接给用户提示

    latest_swipe = Swiped.objects.filter(uid=uid).latest(
        'stime')  # 找到最后一次的滑动记录

    # 对比当前时间和最后一次的滑动时间,差值是否在五分钟内
    passed_time = (now -
                   latest_swipe.stime).total_seconds()  # 计算距离上一次滑动已经过去的秒数
    if passed_time >= 300:
        raise stat.RewindTimeout  # 超过 5 分钟,直接给用户提示

    # 撤销滑动式可能受影响的其他相关数据
    # 好友关系删掉
    if latest_swipe.stype in ['like', 'superlike']:
        Friend.break_off(uid, latest_swipe.sid)

        # 优先推荐队列里的数据删掉
        if latest_swipe.stype == 'superlike':
            rds.lrem(keys.FIRST_RCMD_K % latest_swipe.sid, 1, uid)

    # 撤销滑动积分
    rds.zincrby(keys.RANK_K, -conf.SWIPE_SCORE[latest_swipe.stype],
                latest_swipe.sid)

    # 删除最后一次滑动记录
    latest_swipe.delete()

    # 全部完成后,累加反悔次数
    rds.set(key, rewind_times + 1, 86400 * 2)  # 过期时间是为了让当天的反悔次数自然消失
Exemplo n.º 28
0
def rewind_swiper(uid):
    """
    反悔最近5分钟的操作
    每天只能反悔3次
    """
    # 取出当前时间
    now = datetime.datetime.now()

    # 取出反悔key的过期时间,如果没有给一个默认值
    rewind_key = keys.REWIND_K % (now.date(), uid)
    rewind_times = rds.get(rewind_key, 0)

    # 检查key的反悔次数,如果超过3次则抛出错误
    if rewind_times > 3:
        raise stat.REWIND_TIMEOUT_ERR

    # 从数据库中取出最近滑动记录
    latest_swipe = Swiped.objects.filter(uid=uid).latest('stime')

    # 5分钟内可以撤销滑动,过时则抛错
    pass_time = now - latest_swipe.stime
    if pass_time.total_seconds() > config.TIMEOUT:
        raise stat.REWIND_TIME_ERR

    # 如果是超级喜欢,那么要把自己从对方的优先推荐队列中删去,好友表记录删去
    if latest_swipe.stype == 'superlike':
        rds.lrem(keys.FIRST_RCMD_K % latest_swipe.sid, 1, uid)
        Friends.break_off(latest_swipe.sid, uid)

    # 如果是超级喜欢和喜欢类型,那么要把好友表记录删去
    elif latest_swipe.stype == 'like':
        Friends.break_off(latest_swipe.sid, uid)

    # 调整用户的积分
    score = config.HOT_RANK_SCORE[latest_swipe.stype]
    rds.zincrby(keys.HOT_RANK_K, score, latest_swipe.sid)

    # 删除滑动记录
    latest_swipe.delete()

    # 更新反悔次数
    rds.set(rewind_key, rewind_times + 1, 86400)
Exemplo n.º 29
0
def get(self, *args, **kwargs):
    '''带缓存处理的get方法'''
    model_cls_name = self.model.__name__
    pk = kwargs.get('id') or kwargs.get('pk')
    if pk is not None:
        model_key = keys.MODEL_K % (model_cls_name, pk)
        # 存缓存中获取数据
        model_obj = rds.get(model_key)

        if isinstance(model_obj, self.model):
            return model_obj

    # 缓存中没有数据时, 直接使用原 get 方法从数据库中获取数据
    model_obj = self._get(*args, **kwargs)

    # 将model对象写入缓存
    model_key = keys.MODEL_K % (model_cls_name, model_obj.pk)
    rds.set(model_key, model_obj)

    return model_obj
Exemplo n.º 30
0
def submit_vcode(request):
    '''检查短信验证码,同时进行登陆或者注册'''
    phonenum = request.POST.get('phonenum')
    vcode = request.POST.get('vcode')

    key = keys.VCODE_K % phonenum
    cached_vcode = rds.get(key)
    if vcode and vcode == cached_vcode:
        try:
            user = User.objects.get(phonenum=phonenum)  # 获取用户
            inf_log.info(f'User({user.id}:{user.nickname}) login')
        except User.DoesNotExist:
            user = User.objects.create(phonenum=phonenum, nickname=phonenum)  # 创建新用户
            inf_log.info(f'User({user.id}:{user.nickname}) register')

        # 记录用户登陆状态
        request.session['uid'] = user.id
        return render_json(user.to_dict())
    else:
        raise stat.VcodeErr