import logging import re import json import datetime # from cryptography.utils import cached_property from django.utils.functional import cached_property from django.db.models import Q, Sum, Count from rest_framework import serializers from rest_framework import exceptions from xqcircle.models import CircleUser, CityOfCircle, Circle, Circle2CircleUser, Dynamic, GroupBuy, Conversation, Message, Config, GroupBuyForm, RecommRules, Like, CutKnife, GrouopOwner, Recommend, RealUserInformation, AcademicCertificateRecord, Crowdordering, Order, Matchmaker, IdentifyingCode, MatchmakerAreaConfig, IncomeAndExpenditure from xqcircle import constants from xqcircle import utils from django.conf import settings from xqcircle import tasks as ts logger = logging.getLogger() class CircleUserListSerializer(serializers.ListSerializer): @property def data(self): ret = super(CircleUserListSerializer, self).data for _ in ret: photos_str = ''.join(_['photos']).strip(',') if not photos_str: _['photos'] = [] else: _['photos'] = photos_str.split(',') return ret class CircleUserSerializer(serializers.ModelSerializer): class Meta: model = CircleUser list_serializer_class = CircleUserListSerializer # fields = "__all__" exclude = ['app_id', 'session_key', 'visible_quantity', 'user_status', 'open_id', 'open_gid', 'member_expire_time', 'last_login_time', 'last_city', 'create_time'] # phone = serializers.CharField(max_length=11, required=True, error_messages={ # 'max_length': 'Phone number length exceeds 11', # 'required': "Phone value can not be empty" # }) # career = serializers.CharField(max_length=128, required=True, error_messages={ # 'max_length': "Career value length exceeds 128", # 'required': "Career value can not be empty" # }) # child_introduction = serializers.CharField(max_length=140, required=True, # error_messages={ # 'max_length': "Child_introduction value length exceeds 140", # 'required': "Child_introduction value can not be empty" # }) marriage = serializers.SerializerMethodField() spouse_description = serializers.CharField(max_length=140, required=False, allow_blank=True, error_messages={ 'max_length': "Spouse_description value length exceeds 140", }) # photos = serializers.ListField(required=True, error_messages={ # 'required': "Photos value can not be empty" # }) def get_marriage(self, obj): return constants.MARITAL_STATUS[obj.marriage] # def validate_phone(self, attrs): # r = re.compile(r"^1((3[0-9])|(4[5,7])|(5[0-3,5-9])|(7[0,3,5-8])|(8[0-9])|66|98|99|47)d{8}") # if not isinstance(attrs, str): # raise exceptions.ValidationError("Phone number type error") # if not r.match(attrs): # raise exceptions.ValidationError("Phone number is error") # return attrs # # def validate_career(self, attrs): # if not isinstance(attrs, str): # raise exceptions.ValidationError("Career value type error") # return attrs # # def validate_child_introduction(self, attrs): # if not isinstance(attrs, str): # raise exceptions.ValidationError("Child_introduction value type error") # return attrs # def validate_photos(self, attrs): # if not isinstance(attrs, list): # raise exceptions.ValidationError("Photos value type error") # if not attrs: # raise exceptions.ValidationError("Photos value can not be empty") # url_complie = re.compile(r'(http|https)://[w-_]+(.[w-_]+)+([w-.,@?^=%&:/~+#]*[w-@?^=%&/~+#])?') # for _ in attrs: # if not url_complie.match(_): # raise exceptions.ValidationError("Photo url is error") # return attrs @property def data(self): ret = super(CircleUserSerializer, self).data if isinstance(ret, dict): photos_str = ''.join(ret['photos']).strip(',') if not photos_str: ret['photos'] = [] else: ret['photos'] = photos_str.split(',') return ret class CircleSerializer(serializers.ModelSerializer): class Meta: model = Circle fields = ('id', 'circle_name', 'member_number', 'heat', 'dynamic_number', 'dynamics', 'advertising', 'circle_info', 'single_buy_by_android', 'joined', 'members', 'slogan', 'link_path') members = serializers.SerializerMethodField() dynamics = serializers.SerializerMethodField() advertising = serializers.SerializerMethodField() circle_info = serializers.SerializerMethodField() joined = serializers.SerializerMethodField() slogan = serializers.SerializerMethodField() link_path = serializers.SerializerMethodField() def get_members(self, obj): res = [] host = Circle2CircleUser.objects.filter(circle_id=obj.id, user_type=0).values('user__career', 'user__avatar').first() if host: res.append(host) members = Circle2CircleUser.objects.filter(circle_id=obj.pk, user_type=1, user__card=True).values( 'user__career', 'user__avatar').order_by('-create_time')[:3] res.extend(members) return res def get_dynamics(self, obj): try: dynamics = Dynamic.objects.filter(circle_id=obj.id).order_by( '-weight_h')[:10] serializer = DynamicsSerializer(dynamics, many=True) except Dynamic.DoesNotExist: return [] return serializer.data def get_advertising(self, obj): group_config = Config.objects.filter(itype='wechat_advertising', ikey='circle_{}'.format(obj.pk), ienable=1).values("ival")[0:2] try: return [json.loads(group['ival']) for group in group_config] except: logger.info("群广告配置错误") return [] def get_circle_info(self, obj): """ 圈子介绍语,口号,标签信息 """ ikey = "circle_{}".format(obj.id) circle_config = Config.objects.filter(itype='group_advertising', ikey=ikey, ienable=1).order_by('-id').values( "ival").first() if not circle_config: logger.info('圈子 {} 缺少标签,介绍语等信息') return {} else: try: return json.loads(circle_config['ival']) except: logger.info("{} 圈子标签配置信息json解析错误".format(obj.id)) return {} def get_joined(self, obj): joined = Circle2CircleUser.objects.filter(circle_id=obj.id, user__card=True).values('user_id', 'user__career', 'user__avatar')[:20] return joined # place_of_residence = user.place_of_residence # logger.info('{} {}'.format(user.pk, place_of_residence)) # if place_of_residence: # try: # provice, city = place_of_residence.split('-') # except: # logger.info('{} 格式错误'.format(place_of_residence)) # provice = city = '上海' # else: # provice = city = '上海' # ikey = provice if provice in constants.MUNICIPALITY else city # banner_config = Config.objects.filter(itype='circle_banner', ikey=ikey)[0:3] # if not banner_config: # logger.info('{} 缺少该城市的banner配置') # banner_config = Config.objects.filter(itype='circle_banner', ikey='上海')[0:3] # # try: # return [json.loads(item.ival) for item in banner_config] # except: # logger.info('{} banner解析出错'.format(banner_config)) # return [] def get_slogan(self, obj): """ 圈子介绍语,口号,标签信息 """ ikey = "circle_{}".format(obj.id) circle_config = Config.objects.filter(itype='group_advertising', ikey=ikey, ienable=1).order_by('-id').values( "ival").first() if not circle_config: logger.info('圈子 {} 缺少标签,介绍语等信息') return 0 else: try: return json.loads(circle_config['ival'])['slogan'] except: logger.info("{} 圈子标签配置信息json解析错误".format(obj.id)) return 0 def get_link_path(self, obj): group_config = utils.get_circle_group_config(obj.pk) if group_config: return group_config['link_path'] else: return '' class CirclesSerializer(serializers.ModelSerializer): intro = serializers.SerializerMethodField() # 圈子介绍 is_in = serializers.SerializerMethodField() # 用户是否在圈内 class Meta: model = Circle fields = ( 'id', 'circle_name', 'intro', 'circle_description', 'member_number', 'heat', 'dynamic_number', 'image', 'is_in') def get_intro(self, obj): ikey = "circle_%d" % obj.id circle_config = Config.objects.filter(itype='group_advertising', ikey=ikey, ienable=1).order_by('-id').first() if circle_config: try: return json.loads(circle_config.ival)['intro'] except: logger.info('{} 圈子解析配置出错') return '' else: logger.info('{} 圈子缺少相关标签配置'.format(obj.id)) return '' def get_is_in(self, obj): return Circle2CircleUser.objects.filter(circle_id=obj.pk, user=self.context['request'].user).exists() class GroupBuySerializer(serializers.ModelSerializer): class Meta: model = GroupBuy fields = '__all__' class DynamicsListSerializer(serializers.ListSerializer): @property def data(self): ret = super(DynamicsListSerializer, self).data for _ in ret: _['user_id'] = _['user'] _['circle_id'] = _['circle'] del _['user'] del _['circle'] photos_str = ''.join(_['photos']).strip(',') if not photos_str: _['photos'] = [] else: _['photos'] = photos_str.split(',') return ret class DynamicsSerializer(serializers.ModelSerializer): class Meta: model = Dynamic list_serializer_class = DynamicsListSerializer exclude = ["create_time", "weight_a", "weight_v", "weight_h"] circle = serializers.IntegerField(source='circle.pk', error_messages={ 'required': "Circle value can not be empty", }) user = serializers.CharField(source='user.pk', error_messages={ 'required': "User value can not be empty", }) detail = serializers.CharField(max_length=140, required=False, allow_blank=True, error_messages={ 'max_length': "Detail value length exceeds 140", }) photos = serializers.ListField(required=False) career = serializers.SerializerMethodField() avatar = serializers.SerializerMethodField() age = serializers.SerializerMethodField() gender = serializers.SerializerMethodField() def validate_circle(self, attrs): try: attrs = Circle.objects.get(pk=attrs) except Circle.DoesNotExist: raise exceptions.ValidationError("Circle value is error") return attrs def validate_user(self, attrs): try: attrs = CircleUser.objects.get(pk=attrs) except CircleUser.DoesNotExist: raise exceptions.ValidationError("User value is error") return attrs def validate_photos(self, attrs): if not isinstance(attrs, list): raise exceptions.ValidationError("Photos value type error") url_complie = re.compile('(http|https)://[w-_]+(.[w-_]+)+([w-.,@?^=%&:/~+#]*[w-@?^=%&/~+#])?') for _ in attrs: if not url_complie.match(_): raise exceptions.ValidationError("Photo url is error") return ','.join(attrs) def validate(self, attrs): if not attrs['detail'] and not attrs['photos']: raise exceptions.ValidationError("Detail and Photos cannot be empty at the same time") return attrs def get_career(self, obj): return obj.user.career def get_avatar(self, obj): return obj.user.avatar def get_age(self, obj): return obj.user.age def get_gender(self, obj): return obj.user.gender @property def data(self): ret = super(DynamicsSerializer, self).data if isinstance(ret, dict): ret['user_id'] = ret['user'] ret['circle_id'] = ret['circle'] photos_str = ''.join(ret['photos']).strip(',') if not photos_str: ret['photos'] = [] else: ret['photos'] = photos_str.split(',') del ret['user'] del ret['circle'] return ret def create(self, validated_data): validated_data['circle'] = validated_data['circle']['pk'] validated_data['user'] = validated_data['user']['pk'] return Dynamic.objects.create(**validated_data) class ConversationSerializer(serializers.ModelSerializer): class Meta: model = Conversation # list_serializer_class = DynamicsListSerializer fields = '__all__' user_1_info = serializers.SerializerMethodField() user_2_info = serializers.SerializerMethodField() last_message = serializers.SerializerMethodField() unread_count = serializers.SerializerMethodField() circle_id = serializers.SerializerMethodField() circle_name = serializers.SerializerMethodField() fake_uid = serializers.SerializerMethodField() def get_user_1_info(self, obj): try: res = CircleUser.objects.filter(user_id=obj.user_1_id).values('avatar', 'age', 'career').first() except CircleUser.DoesNotExist: return {} return res def get_user_2_info(self, obj): try: res = CircleUser.objects.filter(user_id=obj.user_2_id).values('avatar', 'age', 'career').first() except CircleUser.DoesNotExist: return {} return res def get_last_message(self, obj): if self.context['request'].user.pk == obj.user_1_id: return obj.last_message or '' else: return obj.last_message_2 or '' def get_unread_count(self, obj): if self.context['request'].user.pk == obj.user_1_id: send_user_id = obj.user_2_id receive_user_id = obj.user_1_id else: send_user_id = obj.user_1_id receive_user_id = obj.user_2_id cur_time = datetime.datetime.now() s_time = cur_time - datetime.timedelta(days=7) count = Message.objects.filter(send_user_id=send_user_id, receive_user_id=receive_user_id, is_effective=True, state=False).filter(create_time__range=(s_time, cur_time)).count() return min(99, count) or '' def get_circle_id(self, obj): if self.context['request'].user.pk == obj.user_1_id: user_id = obj.user_2_id else: user_id = obj.user_1_id circle = utils.get_most_expensive_circle_belong(user_id) if circle: return circle.pk else: return -1 def get_circle_name(self, obj): if self.context['request'].user.pk == obj.user_1_id: user_id = obj.user_2_id else: user_id = obj.user_1_id circle = utils.get_most_expensive_circle_belong(user_id) if circle: return circle.circle_name else: return '' def get_fake_uid(self, obj): if self.context['request'].user.pk == obj.user_1_id: user_id = obj.user_2_id else: user_id = obj.user_1_id return utils.encrypt_uid(user_id) class MessageSerializer(serializers.ModelSerializer): class Meta: model = Message # list_serializer_class = DynamicsListSerializer fields = '__all__' class CityOfCircleSerializer(serializers.ModelSerializer): class Meta: model = CityOfCircle # list_serializer_class = DynamicsListSerializer # fields = '__all__' fields = ('city_name', 'id', 'parent_id') class ConfigsSerializer(serializers.ModelSerializer): class Meta: model = Config # list_serializer_class = DynamicsListSerializer fields = '__all__' class GroupBuyFormSerializer(serializers.ModelSerializer): class Meta: model = GroupBuyForm # list_serializer_class = DynamicsListSerializer fields = '__all__' class RecommStandardSerializer(serializers.ModelSerializer): class Meta: model = RecommRules fields = '__all__' class UserLikeSerializer(serializers.ModelSerializer): conversation_id = serializers.SerializerMethodField() def get_conversation_id(self, obj): conversation = Conversation.objects.filter( Q(user_1_id=obj.from_user_id, user_2_id=obj.to_user_id) | Q(user_1_id=obj.from_user_id, user_2_id=obj.to_user_id)).first() if conversation and obj.is_like: return conversation.pk return -1 class Meta: model = Like fields = ('to_user_id', 'is_like', 'conversation_id') class LikeMeUserSerizlizer(serializers.ModelSerializer): age = serializers.SerializerMethodField() class Meta: model = CircleUser fields = ('user_id', 'open_id', 'create_time', 'gender', 'age', 'place_of_residence', 'education', 'avatar', 'career', 'card') def get_age(self, obj): return obj.age[0:4] class MembersSerializer(serializers.ModelSerializer): class Meta: model = CircleUser fields = ('user_id', 'open_id', 'gender', 'age', 'place_of_residence', 'education', 'avatar', 'career', 'card') class ProfileSerializer(serializers.ModelSerializer): like_count = serializers.SerializerMethodField() # 我喜欢的用户数量 be_like_count = serializers.SerializerMethodField() # 喜欢我的用户数量 info_degree = serializers.SerializerMethodField() # 个人资料完整度 intro_degree = serializers.SerializerMethodField() # 我的介绍完整度 claim_id = serializers.SerializerMethodField() cut_group = serializers.SerializerMethodField() is_real = serializers.SerializerMethodField() # 是否实名 is_phone_auth = serializers.SerializerMethodField() # 是否手机号认证 is_full = serializers.SerializerMethodField() # 必填资料是否全部填写 is_union_id = serializers.SerializerMethodField() # 是否获取 union_id user_type = serializers.SerializerMethodField() # 用户类型 fake_uid = serializers.SerializerMethodField() # 虚拟用户ID is_education = serializers.SerializerMethodField() # 是否学历认证 user_group_type = serializers.SerializerMethodField() # 是否是红娘 class Meta: model = CircleUser fields = ( 'user_id', 'career', 'avatar', 'like_count', 'be_like_count', 'total_money', 'info_degree', 'intro_degree', 'wechat_id', 'claim_id', 'cut_group', 'is_real', 'is_phone_auth', 'gender', 'age', 'place_of_residence', 'is_full', 'is_wechat_visible', 'is_union_id', 'user_type', 'fake_uid', 'is_education', 'user_group_type') def get_like_count(self, obj): return Like.objects.filter(from_user_id=obj.user_id, is_like=True).count() def get_be_like_count(self, obj): user_type = utils.get_user_membership_type(obj) if user_type == 0: return Like.objects.filter(to_user_id=obj.user_id, is_like=True).count() elif utils.is_required_information(obj): # 如果未填写基本资料,则为0 return constants.VISITOR_NUMBER else: return 0 def get_info_degree(self, obj): """个人资料完整度 基本信息:六项,每一项填写权重为10。 性别、出生年月、学历、居住地、职业、身高。 补充信息:五项,每一项填写权重为8。 户籍、住房情况、月收入、婚姻状况、车辆状况。 """ options = ( 'gender', 'age', 'education', 'place_of_residence', 'career', 'height', 'residence', 'house', 'monthly_salary', 'marriage', 'car') proportion = (10,) * 6 + (8,) * 5 return sum(proportion[index] if getattr(obj, choice) else 0 for index, choice in enumerate(options)) def get_intro_degree(self, obj): """我的介绍完整度 文字描述:每一项填写权重为10。 我的介绍、兴趣爱好、感情观、心仪的TA 上传生活照:1张照片权重为20,最多累计权重为 60 。 即用户上传3张照片或9张照片,总权重最多为60。 """ options = ('child_introduction', 'hobbies', 'emotional_view', 'spouse_description') proportion = (10,) * 4 photos = obj.photos.split(',') if obj.photos else [] # 生活照得分 photos_degree = min(60, 20 * sum(1 for p in photos if p.strip())) return sum( proportion[index] if getattr(obj, choice) else 0 for index, choice in enumerate(options)) + photos_degree def get_claim_id(self, obj): group_owner = GrouopOwner.objects.filter(user_id=obj.user_id).first() return group_owner.pk if group_owner else '' def get_cut_group(self, obj): return CutKnife.objects.filter(user_id=obj.user_id, state=1, expire_time__gte=datetime.datetime.now()).values( 'id', 'circle_id', 'circle_name', 'expire_time') def get_is_real(self, obj): # return all([obj.real_name, obj.id_card]) return RealUserInformation.objects.filter(user_id=obj.pk).exists() def get_is_phone_auth(self, obj): return obj.phone != '' def get_is_full(self, obj): return all([obj.gender, obj.age, obj.education, obj.place_of_residence, obj.height, obj.career]) def get_is_union_id(self, obj): return True if obj.union_id else False def get_user_type(self, obj): return utils.get_user_membership_type(obj) def get_fake_uid(self, obj): return utils.encrypt_uid(obj.pk) def get_is_education(self, obj): education_record = AcademicCertificateRecord.objects.filter(user_id=obj.pk) if education_record.filter(state=1).exists(): return 1 else: education = education_record.order_by('-created_time').first() if not education: return 3 else: return education.state def get_user_group_type(self, obj): return 1 if Matchmaker.objects.filter(user_id=obj.pk, state=1).exists() else 0 class RecommUserSerializer(serializers.ModelSerializer): photos = serializers.SerializerMethodField() is_like = serializers.SerializerMethodField() # 用户是否喜欢当前嘉宾 car = serializers.SerializerMethodField() house = serializers.SerializerMethodField() gender = serializers.SerializerMethodField() circle_id = serializers.SerializerMethodField() circle_name = serializers.SerializerMethodField() is_education = serializers.SerializerMethodField() class Meta: model = Recommend fields = ( "recomm_user_id", "photos", "career", "age", "height", "gender", "place_of_residence", "education", "annual_salary", "car", "house", "is_like", "circle_id", "circle_name", "is_education") def get_photos(self, obj): if obj.photos: return obj.photos.split(',') def get_car(self, obj): return '有车' if obj.car > 0 else '没车' def get_house(self, obj): # return '有房' if obj.house > 0 else '没房' return constants.HOUSE_STATUS[obj.house] def get_is_like(self, obj): """ 判断用户是否喜欢当前用户 """ if Like.objects.filter(from_user_id=obj.user_id, to_user_id=obj.recomm_user_id, is_like=True).exists(): return True return False def get_gender(self, obj): return '男' if obj.gender == 1 else '女' def get_circle_id(self, obj): circle = utils.get_most_expensive_circle_belong(obj.recomm_user_id) if circle: return circle.pk else: return -1 def get_circle_name(self, obj): circle = utils.get_most_expensive_circle_belong(obj.recomm_user_id) if circle: return circle.circle_name else: return '' def get_is_education(self, obj): return AcademicCertificateRecord.objects.filter(user_id=obj.recomm_user_id, state=1).exists() class CardSerializer(serializers.ModelSerializer): info = serializers.SerializerMethodField() my_circle = serializers.SerializerMethodField() photos = serializers.SerializerMethodField() is_like = serializers.SerializerMethodField() age = serializers.SerializerMethodField() is_real = serializers.SerializerMethodField() fake_uid = serializers.SerializerMethodField() # 虚拟用户ID is_education = serializers.SerializerMethodField() # 是否学历认证 class Meta: model = CircleUser fields = ( 'photos', 'career', 'gender', 'user_id', 'place_of_residence', 'info', 'my_circle', 'child_introduction', 'hobbies', 'emotional_view', 'spouse_description', 'is_like', 'age', 'education', 'is_real', 'fake_uid', 'is_education') def get_info(self, obj): res = [] marriage_choice = constants.MARITAL_STATUS if obj.marriage: res.append(marriage_choice[obj.marriage]) age = obj.age[0:4] try: age = int(age) except: logger.info("{} 错误".format(obj.age)) age = 0 if age > 0: res.append('{}岁'.format(datetime.datetime.now().year - age)) if obj.height > 0: res.append('{}cm'.format(obj.height)) if obj.monthly_salary: res.append('月薪:{}'.format(obj.monthly_salary)) if obj.car: res.append(obj.car) if obj.house: res.append(obj.house) if obj.career: res.append(obj.career) if obj.place_of_residence: res.append(obj.place_of_residence) return res def get_my_circle(self, obj): return Circle.objects.filter(C2Us__user_id=obj.pk).values('id', 'circle_name') def get_photos(self, obj): return obj.photos.split(',') def get_is_like(self, obj): """ 判断用户是否喜欢当前用户 """ host_id = self.context['request'].user.user_id if Like.objects.filter(from_user_id=host_id, to_user_id=obj.user_id, is_like=True).exists(): return True return False def get_age(self, obj): return obj.age[0:4] def get_is_real(self, obj): # return all([obj.real_name, obj.id_card]) return obj.user_status == 0 or RealUserInformation.objects.filter(user_id=obj.pk).exists() def get_fake_uid(self, obj): return utils.encrypt_uid(obj.pk) def get_is_education(self, obj): return AcademicCertificateRecord.objects.filter(user_id=obj.pk, state=1).exists() class PurchaseSerializer(serializers.ModelSerializer): slogan = serializers.SerializerMethodField() attraction = serializers.SerializerMethodField() discount = serializers.SerializerMethodField() # 折扣 class Meta: model = Circle fields = ( 'id', 'circle_name', 'slogan', 'single_buy_by_android', 'attraction', 'discount') def get_slogan(self, obj): """ 圈子介绍语,口号,标签信息 """ ikey = "circle_{}".format(obj.id) circle_config = Config.objects.filter(itype='group_advertising', ikey=ikey, ienable=1).order_by('-id').values( "ival").first() if not circle_config: logger.info('圈子 {} 缺少标签,介绍语等信息') return 32 else: try: return json.loads(circle_config['ival'])['slogan'] except: logger.info("{} 圈子标签配置信息json解析错误".format(obj.id)) return 32 def get_discount(self, obj): user = self.context['request'].user if obj.single_buy_by_android >= user.total_money: return user.total_money else: return obj.single_buy_by_android def get_intro(self, obj): ikey = "circle_%d" % obj.id circle_config = Config.objects.filter(itype='group_advertising', ikey=ikey, ienable=1).order_by('-id').first() if circle_config: try: return json.loads(circle_config.ival)['intro'] except: logger.info('{} 圈子解析配置出错') return '' else: logger.info('{} 圈子缺少相关标签配置'.format(obj.id)) return '' def get_attraction(self, obj): ikey = "circle_%d" % obj.id circle_config = Config.objects.filter(itype='group_advertising', ikey=ikey, ienable=1).order_by('-id').first() if circle_config: try: return json.loads(circle_config.ival)['attraction'] except: logger.info('{} 圈子解析配置出错') return '' else: logger.info('{} 圈子缺少相关标签配置'.format(obj.id)) return '' class CutKnifeSerializer(serializers.ModelSerializer): class Meta: model = CutKnife fields = ('id', 'expire_time') class GzhCirclesSerializer(serializers.ModelSerializer): class Meta: model = Circle fields = ( "id", "circle_name", "circle_description", "member_number", "heat", "dynamic_number", "single_buy_by_android",) class CrowdorderingSerializer(serializers.ModelSerializer): class Meta: model = Crowdordering fields = ( "expire_time", "is_participate", "is_source", "group_id", "group_type", "is_finish", "gap_number", "avatar", "join_number", "circle_id", "circle_name", "circle_description", "short_desc", "created_time", "remind", "link_path", "is_join_circle_other_group") expire_time = serializers.SerializerMethodField() is_participate = serializers.SerializerMethodField() # is_join = serializers.SerializerMethodField() is_source = serializers.SerializerMethodField() is_finish = serializers.SerializerMethodField() gap_number = serializers.SerializerMethodField() avatar = serializers.SerializerMethodField() join_number = serializers.SerializerMethodField() circle_name = serializers.SerializerMethodField() circle_description = serializers.SerializerMethodField() short_desc = serializers.SerializerMethodField() remind = serializers.SerializerMethodField() link_path = serializers.SerializerMethodField() is_join_circle_other_group = serializers.SerializerMethodField() def get_expire_time(self, obj): self._obj = obj self._user = self.context['request'].user return obj.over_time @cached_property def cached_get_is_participate(self): return (self._obj.sponsor_user_id == self._user.pk) or Order.objects.filter(user_id=self._user.pk, state=1, group_buy_id=self._obj.group_id).exists() def get_is_participate(self, obj): return self.cached_get_is_participate def get_is_source(self, obj): """ 是否是拼单发起者 """ return self._user.pk == self._obj.sponsor_user_id @cached_property def cached_get_is_finish(self): # 当前对改拼单是否完成 return utils.is_user_group_success(self._user, self._obj) def get_is_finish(self, obj): """ 拼单是否完成 """ return self.cached_get_is_finish @cached_property def cached_get_gap_number(self): # 返回问号头像的个数 if self.cached_get_is_finish: return 0 elif self._obj.group_type == 0: return utils.get_group_gap_number(self._obj) - (self.cached_get_is_participate and ( self._user.pk != self._obj.sponsor_user_id)) else: return max(0, utils.get_group_gap_number(self._obj) - self.cached_real_join_number) def get_gap_number(self, obj): return self.cached_get_gap_number @cached_property def cached_get_avatar(self): return utils.get_group_show_avatar(self._user, self._obj) def get_avatar(self, obj): """ 返回需要展示的头像 ( 加上问号头像 ) """ return self.cached_get_avatar + [constants.QUESTION_MARK_AVATAR] * self.cached_get_gap_number @cached_property def cached_real_join_number(self): # 获取拼单真实参与用户 return len(utils.get_group_join_user(self._obj)) + self._obj.group_type def get_join_number(self, obj): # 用户前端显示的参与用户数 (与头像数保持一致) return len(self.cached_get_avatar) @cached_property def cached_get_circle(self): return Circle.objects.get(pk=self._obj.circle_id) def get_circle_name(self, obj): return self.cached_get_circle.circle_name def get_circle_description(self, obj): return self.cached_get_circle.circle_description def get_short_desc(self, obj): return self.cached_get_circle.short_desc def get_remind(self, obj): return "如果超过拼单时间未成功拼单,已支付拼单金额将退还至原支付账户" def get_link_path(self, obj): group_config = utils.get_circle_group_config(obj.circle_id, is_force=True) if group_config: return group_config['link_path'] else: return '' def get_is_join_circle_other_group(self, obj): """ 用户是否参与该圈子的拼单 或 已经进圈 :param obj: :return: """ if Circle2CircleUser.objects.filter(user_id=self._user.pk, circle_id=obj.circle_id) or Order.objects.filter( user_id=self._user.pk, circle_id=obj.circle_id, state=1, is_group=True).exists(): return True else: return False class IdentifyingCodeSerizliser(serializers.ModelSerializer): class Meta: model = IdentifyingCode fields = ( 'id', "user_id", 'phone', 'expired', ) def create(self, validated_data): # logger.info('[create] validated_data=%s', validated_data) phone = validated_data['phone'] r_code, r_expired = validated_data['code'], validated_data['expired'] # 添加验证码白名单 if phone in constants.PHONE_CODE_WHITELIST or settings.IS_DEV: r_code = '000000' r_expired = datetime.datetime(2099, 1, 1) record = IdentifyingCode.objects.create(user_id=self.context["request"].user.user_id, phone=phone, identifying_code=r_code, expired=r_expired) try: ts.send_message_async.delay(record.phone, record.identifying_code) except Exception as e: logger.info('[send_message_async] %s:%s %s', (phone, r_code, e)) return record class MatchmakerAreaConfigSerializer(serializers.ModelSerializer): class Meta: model = MatchmakerAreaConfig fields = ( "id", "area", "money", "detail" ) detail = serializers.SerializerMethodField() def get_detail(self, obj): try: detail = json.loads(obj.detail) except Exception: detail = {} return detail class MatchmakerSerializer(serializers.ModelSerializer): class Meta: model = Matchmaker fields = ( "user_id", "phone", "avatar", "place_of_residence", "crowdordering_royalty", "today_crowdordering_royalty", "inferior_num", "today_inferior_num" ) crowdordering_royalty = serializers.SerializerMethodField() today_crowdordering_royalty = serializers.SerializerMethodField() inferior_num = serializers.SerializerMethodField() today_inferior_num = serializers.SerializerMethodField() def get_crowdordering_royalty(self, obj): money = IncomeAndExpenditure.objects.filter(user_id=obj.user_id, state=1, source=1).aggregate( total=Sum("operate_money")) return money["total"] if money and money["total"] else 0 def get_today_crowdordering_royalty(self, obj): money = IncomeAndExpenditure.objects.filter(user_id=obj.user_id, state=1, source=1, created_time__gte=datetime.date.today()).aggregate( total=Sum("operate_money")) return money["total"] if money and money["total"] else 0 def get_inferior_num(self, obj): return IncomeAndExpenditure.objects.filter(user_id=obj.user_id, state=1, source=2).count() def get_today_inferior_num(self, obj): return IncomeAndExpenditure.objects.filter(user_id=obj.user_id, state=1, source=2, created_time__gte=datetime.date.today()).count() @property def data(self): ret = super(MatchmakerSerializer, self).data result = {"errcode": 0, "detail": "success", "data": ret} return result