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秒
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秒
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))
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
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('验证码错误')
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)
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
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])
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())
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)
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)
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)
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)
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)
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)
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)
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())
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)
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())
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)
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
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) # 向用户手机发送验证码
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)
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
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)
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)
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) # 过期时间是为了让当天的反悔次数自然消失
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)
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
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