def put(self, request, address_id): # 1.接收参数 json_dict = json.loads(request.body.decode()) receiver = json_dict.get('receiver') province_id = json_dict.get('province_id') city_id = json_dict.get('city_id') district_id = json_dict.get('district_id') place = json_dict.get('place') mobile = json_dict.get('mobile') tel = json_dict.get('tel') email = json_dict.get('email') # 2.正则校验 if not all([receiver, province_id, city_id, district_id, place, mobile]): return http.HttpResponseForbidden('缺少必传参数') if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('参数mobile有误') if tel: if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel): return http.HttpResponseForbidden('参数tel有误') if email: if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email): return http.HttpResponseForbidden('参数email有误') try: # 3.修改数据 # 修改完毕返回的是 0 1 -1 --返回前端dict--->重新获取修改完毕的内容 Address.objects.filter(id=address_id).update( user=request.user, title=receiver, receiver=receiver, province_id=province_id, city_id=city_id, district_id=district_id, place=place, mobile=mobile, tel=tel, email=email ) except Exception as e: logger.error(e) return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '更新地址失败'}) # 4.返回前端 需要的dict 进行局部更新 address = Address.objects.get(id=address_id) address_dict = { "id": address.id, "title": address.title, "receiver": address.receiver, "province": address.province.name, "city": address.city.name, "district": address.district.name, "place": address.place, "mobile": address.mobile, "tel": address.tel, "email": address.email } # 响应更新地址结果 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '更新地址成功', 'address': address_dict})
def put(self, request): # 1.接收 请求体非表单参数 json json_bytes = request.body json_str = json_bytes.decode() json_dict = json.loads(json_str) email = json_dict.get('email') # 2.正则校验邮箱 if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email): return http.HttpResponseForbidden('参数email有误') # 3.修改 数据库中 email 值 try: request.user.email = email request.user.save() except Exception as e: logger.error(e) return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '添加邮箱失败'}) # 自动发邮件(需要加密) token_value = { 'user_id': request.user.id, 'email': email } # 加密 --->对象方法SecretOauth() from utils.secret import SecretOauth secret_str = SecretOauth().dumps(token_value) # http://www.meiduo.site:8000/emails/verification/?token={%22user_id%22:%201,%20%22email%22:%20%[email protected]%22} verify_url = settings.EMAIL_ACTIVE_URL + "?token=" + secret_str from celery_tasks.email.tasks import send_verify_email send_verify_email.delay(email, verify_url) # 4.返回前端结果 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加邮箱成功'})
def delete(self, request, address_id): # 1.接收解析参数 # 2.修改 is_deleted=True try: Address.objects.get(id=address_id).update(is_deleted=True) except Exception as e: logger.error(e) return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '删除地址失败'}) return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除地址成功'})
def check_verify_email_token(token): # 解密 from utils.secret import SecretOauth json_dict = SecretOauth().loads(token) # 校验用户是否存在 同时邮箱也匹配 try: user = User.objects.get(id=json_dict['user_id'], email=json_dict['email']) except Exception as e: logger.error(e) return None else: return user
def put(self, request, address_id): # 1.接收参数 try: # 2.查询当前地址 address = Address.objects.get(id=address_id) # 3.修改user的 default_address request.user.default_address = address request.user.save() except Exception as e: logger.error(e) return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置默认地址失败'}) # 4.返回响应对象 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '设置默认地址成功'})
def put(self, request, address_id): # 1.接收参数 json_dict = json.loads(request.body.decode()) title = json_dict.get('title') try: # 2.查询当前用户地址 address = Address.objects.get(id=address_id) # 3.设置新的地址标题 address.title = title address.save() except Exception as e: logger.error(e) return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置地址标题失败'}) # 4.返回响应对象 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '设置地址标题成功'})
def get(self, request): # 1.接收参数 json_str = request.GET.get('token') # 校验用户是否存在 同时邮箱也匹配 user = check_verify_email_token(json_str) if not user: return http.HttpResponseForbidden('无效的token') # 2.修改对象的 email_active 字段 try: user.email_active = True user.save() except Exception as e: logger.error(e) return http.HttpResponseForbidden('激活邮箱失效了!') # 3.返回响应结果 return redirect(reverse('users:info'))
def post(self, request): """实现修改密码逻辑""" # 接收参数 old_password = request.POST.get('old_pwd') new_password = request.POST.get('new_pwd') new_password2 = request.POST.get('new_cpwd') # 校验参数 if not all([old_password, new_password, new_password2]): return http.HttpResponseForbidden('缺少必传参数') # 校验密码是否正确check_password result = request.user.check_password(old_password) # result 为false 密码不正确 if not result: return render(request, 'user_center_pass.html', {'origin_pwd_errmsg': '原始密码错误'}) if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password): return http.HttpResponseForbidden('密码最少8位,最长20位') if new_password != new_password2: return http.HttpResponseForbidden('两次输入的密码不一致') # 修改密码 --> 改完的密码需要加密set_password try: request.user.set_password(new_password) request.user.save() except Exception as e: logger.error(e) return render(request, 'user_center_pass.html', {'change_pwd_errmsg': '修改密码失败'}) # 清理状态保持信息 logout(request) response = redirect(reverse('users:login')) response.delete_cookie('username') # # 响应密码修改结果:重定向到登录界面 return response
def post(self, request): # 判断是否超过地址上限:最多20个 count = Address.objects.filter(user=request.user, is_deleted=False).count() # count = request.user.addresses.filter(is_deleted=False).count() if count >= contants.USER_ADDRESS_COUNTS_LIMIT: return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '超过地址数量上限'}) # 1.接收参数 JSON dict(bytes-->string) json_dict = json.loads(request.body.decode()) receiver = json_dict.get('receiver') province_id = json_dict.get('province_id') city_id = json_dict.get('city_id') district_id = json_dict.get('district_id') place = json_dict.get('place') mobile = json_dict.get('mobile') tel = json_dict.get('tel') email = json_dict.get('email') # 2.正则校验 if not all([receiver, province_id, city_id, district_id, place, mobile]): return http.HttpResponseForbidden('缺少必传参数') if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('参数mobile有误') if tel: if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel): return http.HttpResponseForbidden('参数tel有误') if email: if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email): return http.HttpResponseForbidden('参数email有误') # 3.create # 保存地址信息 try: address = Address.objects.create( user=request.user, title=receiver, receiver=receiver, province_id=province_id, city_id=city_id, district_id=district_id, place=place, mobile=mobile, tel=tel, email=email ) # 设置默认地址 default_address = request.user.default_address if not default_address: request.user.default_address = address request.user.save() except Exception as e: logger.error(e) return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '新增地址失败'}) # 4.构建前端 dict address_dict = { "id": address.id, "title": address.title, "receiver": address.receiver, "province": address.province.name, "city": address.city.name, "district": address.district.name, "place": address.place, "mobile": address.mobile, "tel": address.tel, "email": address.email } # 5.返回 JsonResponse: dict-->JSONstring return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '新增地址成功', 'address': address_dict})
def post(self, request): # <1> 接收解析参数 username = request.POST.get('username') # username = request.POST('username') ‘QueryDict’ object is not callable(调用) password = request.POST.get('password') password2 = request.POST.get('password2') mobile = request.POST.get('mobile') allow = request.POST.get('allow') # <2> 校验参数 # * 0.判空 # if not all([username, password, password2, mobile, allow]): # return http.HttpResponseForbidden('缺少参数!') # * 1.用户名: ---------判空,正则校验,是否重复 if not re.match('^[a-zA-Z0-9_-]{5,20}$', username): return http.HttpResponseForbidden('请输入5-20个字符的用户名') # 判断用户名是否重复 ---- username-->给后台传递-->接收参数-->后台2次校验参数-->查询filter().count() # * 2.密码: --------- 判空,正则校验 if not re.match('^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20位的密码') # * 3.确认密码: ---------判空,判断是否相等 if password2 != password: return http.HttpResponseForbidden('两次密码输入不一致') # * 4.手机号:--------- 判空,正则校验,是否重复 if not re.match('^1[345789]\d{9}$', mobile): return http.HttpResponseForbidden('请输入正确的手机号码') # * 5.图形验证码 # * 6.短信验证码 sms_code = request.POST.get('msg_code') from django_redis import get_redis_connection sms_client = get_redis_connection('sms_code') sms_code_redis = sms_client.get('sms_%s' % mobile) if sms_code_redis is None: return render(request, 'register.html', {'sms_code_errmsg': '无效的短信验证码'}) # 删除 sms_code_redis sms_client.delete('sms_%s' % mobile) if sms_code != sms_code_redis.decode(): return render(request, 'register.html', {'sms_code_errmsg': '短信验证码有误!'}) # * 7.同意”美多商城用户使用协议“: 判断是否选中 if allow != 'on': return http.HttpResponseForbidden('请求协议!') # # <3> 注册用户 # Duplicate(重复) entry 'itcast1' for key 'username' # 交互数据库的地方 最好预处理 try: # from apps.users.models import User --> 自定义用户类User user = User.objects.create_user(username=username, password=password, mobile=mobile) except Exception as e: logger.error(e) return render(request, 'register.html') # <4> 保持登录状态:cookie --session(django自带) # from django.contrib.auth import login login(request, user) # redis-cli # 127.0.0.1:6379> keys * # 1) "django_redis_key" # 127.0.0.1:6379> select 1 # OK # 127.0.0.1:6379[1]> keys * # 1) ":1:django.contrib.sessions.cachekd572q3dxu4g6oxagre9bcor1w5o8wxb" # 127.0.0.1:6379[1]> get :1:django.contrib.sessions.cachekd572q3dxu4g6oxagre9bcor1w5o8wxb # "\x80\x04\x95\x97\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x0f_auth_user_hash\x94\x8c(63f00bc33873fb5c9317bc8366da5d8676531df8 # \x94\x8c\r_auth_user_id\x94\x8c\x018\x94\x8c\x12_auth_user_backend\x94\x8c)django.contrib.auth.backends.ModelBackend\x94u." # <5> 重定向到首页 # return http.HttpResponse('重定向到首页') # 响应注册结果 response = redirect(reverse('contents:index')) # 注册时用户名写入到cookie,有效期15天 response.set_cookie('username', user.username, max_age=3600 * 24 * 15) return response
def get(self, request, mobile): # 1. 接收 2个 mobile; 图片验证码img_code uuid = request.GET.get('image_code_id') image_code = request.GET.get('image_code') # 2.验证码 img_code和redis存储的验证码 是否一致 (1.redis取出来(4步) 2.判断是否相等 3.redis img_code 删除) from django_redis import get_redis_connection img_client = get_redis_connection('verify_image_code') img_code_redis = img_client.get('img_%s' % uuid) # 2.1 判断是否为空 if img_code_redis is None: return http.JsonResponse({'code': "4001", 'errmsg': '图形验证码失效了'}) # 2.2 删除图片验证码 try: img_client.delete('img_%s' % uuid) except Exception as e: logger.error(e) # 2.3 判断是否相等 千万注意: redis返回的是bytes类型 if img_code_redis.decode().lower() != image_code.lower(): return http.JsonResponse({'code': "4001", 'errmsg': '输入图形验证码有误'}) print('成功没有!') # 3.生成随机6位 短信验证码内容 random.randit() from random import randint sms_code = "%06d" % randint(0, 999999) # 4.存储 随机6位 redis(3步) sms_client = get_redis_connection('sms_code') print(sms_code) # 后台避免 短信验证码重复流程 # (1)获取 频繁发送短信的 标识 send_flag = sms_client.get('send_flag_%s' % mobile) # (2)判断标识是否存在 if send_flag: # return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '发送短信过于频繁'}) return http.JsonResponse({'code': "4002", 'errmsg': '发送短信过于频繁666'}) # (3)标识不存在, 重新倒计时 # 保存短信验证码 # sms_client.setex('sms_%s' % mobile, contants.SMS_CODE_REDIS_EXPIRE, sms_code) # 重新写入send_flag # sms_client.setex('send_flag_%s' % mobile, contants.SEND_SMS_CODE_INTERVAL, 1) # pipeline操作Redis数据库---> 通过减少客户端与Redis的通信次数来实现降低往返延时时间 # 创建Redis管道 pl = sms_client.pipeline() # 将Redis请求添加到队列 pl.setex('sms_%s' % mobile, contants.SMS_CODE_REDIS_EXPIRE, sms_code) pl.setex('send_flag_%s' % mobile, contants.SEND_SMS_CODE_INTERVAL, 1) # 执行请求 pl.execute() # 5.发送短信-- 第三方联容云-- # from libs.yuntongxun.sms import CCP # CCP().send_template_sms('手机号', ['验证码', '过期时间5分钟'], 短信模板1) # CCP().send_template_sms(mobile, [sms_code, 5], 1) # print("当前验证码是:", sms_code) # 使用异步发---触发任务 from celery_tasks.sms.tasks import ccp_send_sms_code ccp_send_sms_code.delay(mobile, sms_code) # 6.返回响应对象 return http.JsonResponse({'code': '0', 'errmsg': '发送短信成功'})
def get(self, request): # 1.接收参数 area_id = request.GET.get('area_id') from django.core.cache import cache if not area_id: # 1 读取省份缓存数据 province_list = cache.get('province_list') if not province_list: try: # 2.省的数据 area_id 为空 province_model_list = Area.objects.filter( parent__isnull=True) # 将 ORM 的数据对象 转换成 给前端需要的 JSON 格式 province_list = [] for pro in province_model_list: province_list.append({'id': pro.id, 'name': pro.name}) except Exception as e: logger.error(e) return JsonResponse({ 'code': RETCODE.DBERR, 'errmsg': '省份数据错误' }) # 存储省份缓存数据 cache.set('province_list', province_list, 3600) return JsonResponse({ 'code': RETCODE.OK, 'errmsg': 'OK', 'province_list': province_list }) else: # 3.市区的数据 area_id 有值 # 1 读取省份缓存数据 sub_data = cache.get('subs_%s' % area_id) if not sub_data: # 提供市或区数据 try: # city_model_list = Area.objects.filter(parent_id=area_id) parent_model = Area.objects.get(id=area_id) # 查询市或区的父级 sub_model_list = parent_model.subs.all() # 将 ORM 的数据对象 转换成 给前端需要的 JSON 格式 subs_list = [] for city in sub_model_list: subs_list.append({'id': city.id, 'name': city.name}) sub_data = { 'id': parent_model.id, 'name': parent_model.name, 'subs': subs_list } except Exception as e: logger.error(e) return JsonResponse({ 'code': RETCODE.DBERR, 'errmsg': '城市或区数据错误' }) cache.set('subs_%s' % area_id, sub_data, 3600) return JsonResponse({ 'code': RETCODE.OK, 'errmsg': 'OK', 'sub_data': sub_data })