class Meta: # 模型 model = Client # 序列化字段 fields = '__all__' # 级联层级 depth = 0 # 只读字段 read_only_fields = ('create_time', 'update_time', 'is_delete', # 公共字段 'secret_key', 'pushed_num') # 而外参数 extra_kwargs = SerializerUtil.get_extra_kwargs(model=model, read_only_fields=read_only_fields, validators={'name': [UniqueValidator(queryset=Client.objects.all(), message='客户已被注册')]})
class Meta: # 模型 model = Report # 序列化字段 fields = '__all__' # 级联层级 depth = 0 # 只读字段 # read_only_fields = ('create_time', 'update_time', 'is_delete', # 公共字段 # ) read_only_fields = tuple(utils.get_model_fields(model, exclude_list=[])) # 而外参数 extra_kwargs = SerializerUtil.get_extra_kwargs( model=model, read_only_fields=read_only_fields)
class Meta: # 模型 model = RechargeRecord # 序列化字段 fields = '__all__' # 级联层级 depth = 0 # 只读字段 read_only_fields = ( 'create_time', 'update_time', 'is_delete', # 公共字段 ) # 而外参数 extra_kwargs = SerializerUtil.get_extra_kwargs( model=model, read_only_fields=read_only_fields)
class Meta: # 模型 model = PushRecord # 序列化字段 fields = '__all__' # 级联层级 depth = 0 # 只读字段 read_only_fields = ( 'create_time', 'update_time', 'is_delete', # 公共字段 'result', 'response_message', 'client') # 而外参数 extra_kwargs = SerializerUtil.get_extra_kwargs( model=model, read_only_fields=read_only_fields)
class Meta: # 模型 model = User # 序列化字段 fields = '__all__' # 级联层级 depth = 0 # 只读字段 read_only_fields = ('create_time', 'update_time', 'is_delete', # 公共字段 'last_login', 'is_superuser', 'first_name', 'last_name', 'date_joined', 'groups', 'user_permissions', 'is_staff', 'is_active') # 而外参数 extra_kwargs = SerializerUtil.get_extra_kwargs(model=model, read_only_fields=read_only_fields, write_only_fields=('password'), validators={ 'username': [UniqueValidator(queryset=User.objects.all(), message='用户名已经存在')] }, style={ 'password': {'input_type': 'password'} } )
class PushRecordSerializer(serializers.ModelSerializer, MyBaseSerializer): """ 推送记录 """ msg = serializers.JSONField(required=True, **SerializerUtil.get_serializer_item( 'msg', PushRecord, exclude=('max_length', 'invalid'))) def validate_mobile(self, data): if not utils.validate_mobile(data): serializers.ValidationError('电话号码不合法') return data def validate_secret_key(self, data): client = Client.objects.filter(secret_key=data).first() # 密匙无效 if not client: raise serializers.ValidationError('该密匙(%s)没有对应用户' % data) # 客户账号被关闭 if client and client.is_delete: raise serializers.ValidationError('该密匙(%s)对应用户(%s)已被冻结, 请联系管理员处理' % (data, client)) return data def validate(self, attrs): # 获取当前请求的ip _ip = self.context['request'].META.get("REMOTE_ADDR") # 获取ip白名单 ip_while_list = [] # 检测ip # if not _ip in ip_while_list: # raise serializers.ValidationError('ip: %(ip)s, 不在ip白名单, 请联系管理员添加' % {'ip': _ip}) # 校验用户可推送次数 _push_num = 1 _client = Client.objects.filter(secret_key=attrs['secret_key']).first() # 可推送数量需要重新查询 防止并发出错 if not Client.objects.filter(id=_client.id, push_num__gte=_push_num): raise serializers.ValidationError( '客户:%(client)s 可推送次数不足%(push_num)d次 请充值!!!' % dict({ 'push_num': _push_num, 'client': _client.name })) return attrs @transaction.atomic def create(self, validated_data): from sms_middleground.settings import ACCESS_KEY_ID, ACCESS_KEY_SECRET, SMS_DEBUG # 获取客户信息 _client = Client.objects.filter( secret_key=validated_data['secret_key']).first() # 客户 # 记录客户信息 validated_data['client'] = _client # 获取客户保存的阿里账号AccessKeyId # 获取客户保存的阿里账号AccessKeySecret if _client.access_key_id: _access_key_id = _client.access_key_id _access_key_secret = _client.access_key_secret else: _access_key_id = ACCESS_KEY_ID _access_key_secret = ACCESS_KEY_SECRET # 获取短信签名名称 _sign_name = _client.sign_name if _client.sign_name else '锐掌网络' # 保存签名名称 validated_data['sign_name'] = _sign_name # 创建短信对象 from my_sms.sms import AliSms sms = AliSms(_access_key_id, _access_key_secret) # 是否非测试环境 if not SMS_DEBUG: # 本次推送次数 _push_num = 1 # 保存数据库可推送数量 _client_push_num = _client.push_num # 推送消息 使用乐观锁更新可推送能够次数 if Client.objects.filter(id=_client.id, push_num__gte=_push_num).update( push_num=F('push_num') - _push_num): # 发送短信 result = sms.send_sms(sign_name=_sign_name, mobile=validated_data['mobile'], code=validated_data['template_code'], msg=validated_data['msg']) # 保存平台返回的报文 validated_data['response_message'] = result _res_json = json.loads(result) # 消息发送结果判断 if _res_json['Code'] == 'OK': validated_data['result'] = 'success' # 判断预警次数是否大于等于可用次数 client = Client.objects.filter(id=_client.id).first() if client.warn_limit >= client.push_num: # 通知用户 warn_mobile = client.mobile print('次数预警 %(mobile)s' % {'mobile': warn_mobile}) else: validated_data['result'] = 'fail' # 推送失败返还次数 Client.objects.filter(id=_client.id).update( push_num=F('push_num') + _push_num) else: # 回填返回数据 validated_data['result'] = 'fail' validated_data['response_message'] = '用户:%(client)s 可推送次数不足%(push_num)d次 请充值!!!' % \ {'client': _client.name, 'push_num': _push_num} else: validated_data['result'] = 'debug' # 模拟数据 # import random, datetime # validated_data['create_time'] = datetime.datetime.now() # for i in range(100): # client = None # while not client: # client_id = random.randint(1, 9) # client = Client.objects.filter(id=client_id).first() # result = random.choice(['success', 'success', 'success', 'fail', 'fail', 'fail', 'warn', 'error']) # mobile = random.choice(['18149540000', '18149540001', '18149540002', '18149540003', '18149540004', # '18149540005', '18149540006', '18149540007']) # date = datetime.datetime.now() - datetime.timedelta(days=random.randint(0, 9)) # code = int(''.join(random.sample(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], 6))) # PushRecord.objects.create(mobile=mobile, # msg='{"code": %d}' % code, # template_code='', # sign_name=client.sign_name, # result=result, # response_message='', # secret_key=client.secret_key, # client=client, # create_time=date) # 保存推送记录 instance = super(PushRecordSerializer, self).create(validated_data) return instance class Meta: # 模型 model = PushRecord # 序列化字段 fields = '__all__' # 级联层级 depth = 0 # 只读字段 read_only_fields = ( 'create_time', 'update_time', 'is_delete', # 公共字段 'result', 'response_message', 'client') # 而外参数 extra_kwargs = SerializerUtil.get_extra_kwargs( model=model, read_only_fields=read_only_fields)