class RolesSerializerMixin(serializers.Serializer): system_roles = serializers.ManyRelatedField( child_relation=serializers.PrimaryKeyRelatedField( queryset=Role.system_roles), label=_('System roles'), ) org_roles = serializers.ManyRelatedField( required=False, child_relation=serializers.PrimaryKeyRelatedField( queryset=Role.org_roles), label=_('Org roles'), ) system_roles_display = serializers.SerializerMethodField( label=_('System roles')) org_roles_display = serializers.SerializerMethodField(label=_('Org roles')) @staticmethod def get_system_roles_display(user): return user.system_roles.display @staticmethod def get_org_roles_display(user): return user.org_roles.display def pop_roles_if_need(self, fields): request = self.context.get('request') view = self.context.get('view') if not all([request, view, hasattr(view, 'action')]): return fields if request.user.is_anonymous: return fields action = view.action or 'list' if action in ('partial_bulk_update', 'bulk_update', 'partial_update', 'update'): action = 'create' model_cls_field_mapper = { SystemRoleBinding: ['system_roles', 'system_roles_display'], OrgRoleBinding: ['org_roles', 'system_roles_display'] } for model_cls, fields_names in model_cls_field_mapper.items(): perms = RBACPermission.parse_action_model_perms(action, model_cls) if request.user.has_perms(perms): continue # 没有权限就去掉 for field_name in fields_names: fields.pop(field_name, None) return fields def get_fields(self): fields = super().get_fields() self.pop_roles_if_need(fields) return fields
class TaskSerializer(serializers.ModelSerializer): class Meta: model = Task class InnerTestSerializer(serializers.ModelSerializer): class Meta: model = Test fields = ('id', 'name', 'owner', 'repository_url', 'detail_url', 'external_links') repository_url = serializers.CharField(source='get_reposituory_url') detail_url = serializers.CharField(source='get_detail_url') # external_links = serializers.StringRelatedField(source='get_external_links') class InnerRecipeSerializer(RecipeSerializer): class Meta: model = Recipe exclude = ('tasks', ) test = InnerTestSerializer() # result = ResultField() # status = StatusField() # statusbyuser = StatusByUserField() recipe = InnerRecipeSerializer() comments = serializers.ManyRelatedField(child_relation=CommentSerializer()) logfiles = serializers.StringRelatedField(many=True)
class CommentReadModelSerializer(serializers.ModelSerializer): results = serializers.ManyRelatedField( child_relation=CommentModelSerializer(), source='ordergoods_set') class Meta: model = GoodsSKU fields = ['results']
class TaskSerializer(serializers.ModelSerializer): class Meta: model = Task fields = '__all__' class InnerTestSerializer(serializers.ModelSerializer): class Meta: model = Test fields = ('id', 'name', 'owner', 'repository_url', 'detail_url', 'external_links', "get_absolute_url") repository_url = serializers.CharField(source='get_reposituory_url') detail_url = serializers.CharField(source='get_detail_url') # external_links = serializers.StringRelatedField(source='get_external_links') class InnerRecipeSerializer(RecipeSerializer): class Meta: model = Recipe # fields = "__all__" fields = ("id", "uid", "job", "arch", "comments") # from rest framework 3.3 is not possible set exclude = ('tasks', ) # exclude = ('tasks', ) test = InnerTestSerializer() # result = ResultField() # status = StatusField() # statusbyuser = StatusByUserField() recipe = InnerRecipeSerializer() comments = serializers.ManyRelatedField(child_relation=CommentSerializer()) logfiles = serializers.StringRelatedField(many=True)
class ShortIncidentSerializer(serializers.ModelSerializer): id = serializers.ManyRelatedField(child_relation=incident_id) depth = 3 class Meta: model = Incident fields = ('id', 'pos_lon', 'pos_lan', 'created_at')
class QuestionSerializer(serializers.Serializer): """ Default Question serializer with all available fields """ id = serializers.IntegerField() question_title = serializers.CharField(required=True, allow_blank=False, max_length=100) author = serializers.CharField(required=True, allow_blank=False, max_length=100) pub_date = serializers.DateTimeField(format="%x %X") question_tags = serializers.ManyRelatedField(child_relation=serializers.CharField()) question_text = serializers.CharField(required=True, allow_blank=False, max_length=2000) number_of_answers = serializers.SerializerMethodField() rating = serializers.IntegerField() def create(self, validated_data): """ No change with api available """ pass def update(self, instance, validated_data): """ No change with api available """ pass def get_number_of_answers(self, obj): """ :return: number of answers for number_of_answer field """ return obj.answer_set.count()
class UserUpdateSerializer(serializers.Serializer): account = serializers.CharField(required=False) username = serializers.CharField(required=False) mobile = serializers.CharField(required=False) status = serializers.IntegerField(required=False) bran = serializers.PrimaryKeyRelatedField( label='所属分部', help_text='所属分部', queryset=BranchesInfo.objects.all(), required=False) roles = serializers.ManyRelatedField( child_relation=serializers.PrimaryKeyRelatedField( label='所属角色', help_text='用户关联的角色', queryset=RolesInfo.objects.all()), help_text='用户关联的角色', required=False, label='所属角色') def update(self, instance, validated_data): roles = validated_data.pop('roles') request_user = self.context.get('request').user if isinstance(request_user, AnonymousUser): request_user = None validated_data['modifier'] = request_user with transaction.atomic(): for attr in validated_data.keys(): setattr(instance, attr, validated_data.get(attr)) instance.roles.set(roles) instance.save() return instance
class CategoryAuthUserSerializer(serializers.ModelSerializer): """Категории авторизованного пользователя""" links = serializers.ManyRelatedField(child_relation=LinkSetSerializer(), source='link_set') class Meta: model = Category fields = ['id', 'name', 'links']
class UsersSerializerAnti(serializers.ModelSerializer): """用户序列反化器""" roles = serializers.ManyRelatedField( child_relation=serializers.PrimaryKeyRelatedField( label='所属角色', help_text='用户关联的角色', queryset=RolesInfo.objects.all()), help_text='用户关联的角色', required=False, label='所属角色') creator = serializers.StringRelatedField(read_only=True) modifier = serializers.SlugRelatedField(read_only=True, slug_field='username') date_joined = serializers.DateTimeField(read_only=True, required=False, format='%Y-%m-%d %H:%M:%S') modify_time = serializers.DateTimeField(read_only=True, required=False, format='%Y-%m-%d %H:%M:%S') class Meta: model = UsersInfo fields = [ 'id', 'account', 'username', 'password', 'mobile', 'status', 'bran', 'roles', 'creator', 'modifier', 'date_joined', 'modify_time', ] extra_kwargs = { 'id': { 'read_only': True }, 'password': { 'write_only': True }, } def create(self, validated_data): roles = validated_data.pop('roles') request_user = self.context.get('request').user if isinstance(request_user, AnonymousUser): request_user = None validated_data['creator'] = request_user validated_data['modifier'] = validated_data.get('creator') with transaction.atomic(): user = UsersInfo.objects.create_user(**validated_data) user.roles.set(roles) user.save() return user
class OrderInfoReadModelSerializer(serializers.ModelSerializer): # 查询该订单的所有的商品 goods = serializers.ManyRelatedField(OrderGoodsModelSerializer(), source='ordergoods_set') class Meta: model = models.OrderInfo fields = '__all__'
class CategorySerializer(serializers.ModelSerializer): """Список всех категорий""" owner = UserProjectSerializer() links = serializers.ManyRelatedField(child_relation=LinkSetSerializer(), source='link_set') class Meta: model = Category fields = ['id', 'name', 'owner', 'links']
class SentSerializer(serializers.ModelSerializer): TO = serializers.ManyRelatedField(UserEmailSerializer(), source='email.to_users') title = serializers.CharField(source='email.title') text = serializers.CharField(source='email.text') class Meta: model = Sent fields = ('TO', 'title', 'text', 'is_new')
class BaseGroupSerializer(serializers.ModelSerializer): permissions_list = BasePermissionSeializer(many=True, read_only=True, source='permissions') permissions = serializers.ManyRelatedField( child_relation=serializers.PrimaryKeyRelatedField( queryset=Permission.objects.all(), many=True, allow_null=True), allow_null=True) class Meta: model = Group fields = ('__all__')
class QuestionSerializer(serializers.Serializer): """ Question serializer with all fields """ id = serializers.IntegerField() title = serializers.CharField(required=True, allow_blank=False, max_length=100) author = serializers.CharField(required=True, allow_blank=False, max_length=100) pub_date = serializers.DateTimeField(format="%x %X") tags = serializers.ManyRelatedField(child_relation=serializers.CharField()) text = serializers.CharField(required=True, allow_blank=False, max_length=2000) number_of_answers = serializers.SerializerMethodField() rank = serializers.IntegerField() def get_number_of_answers(self, obj): """ :return: number of answers for number_of_answer field """ return obj.answer_set.count()
class EmailSerializer(serializers.ModelSerializer): FROM = UserEmailSerializer(read_only=True, source='from_user') TO = serializers.ManyRelatedField(UserEmailSerializer(), source='to_users') class Meta: model = Email fields = ('FROM', 'TO', 'title', 'text') def validate_TO(self, value): request = self.context['request'] users = [] for email in set(value): try: users.append(User.objects.get(email=email)) except User.DoesNotExist: messages.error(request, f'Email address "{email}" does not exist') if users: emails_string = '", "'.join((u.email for u in users)) message = f'Email sent to: "{emails_string}"' messages.success(request, message) return users raise ValidationError('Check the email addresses into the "TO" field')
class BookmarkSerializer(serializers.ModelSerializer): tags = serializers.ManyRelatedField(source='tags') class Meta: model = Bookmark exclude = ('id', )
class UserSerializer(BaseModelSerializer): username = EmailField(max_length=75, allow_blank=False) first_name = serializers.CharField(max_length=30, allow_blank=True) last_name = serializers.CharField(max_length=30, allow_blank=True) email = EmailField(max_length=75, allow_blank=False) is_active = serializers.BooleanField(required=True) trading_desk = serializers.CharField(required=True, allow_blank=False) is_manage_user = serializers.BooleanField(read_only=True) date_joined = DateTimeField(read_only=True) user_in_groups = ListField(required=True) groups = serializers.ManyRelatedField( required=False, child_relation=serializers.PrimaryKeyRelatedField( queryset=Group.objects.all())) reset_password_url = serializers.CharField(required=True) required_in_schema = ['first_name', 'last_name', 'groups'] # pylint: disable=old-style-class class Meta: model = User fields = ('user_id', 'username', 'first_name', 'last_name', 'full_name', 'email', 'is_active', 'user_in_groups', 'groups', 'trading_desk', 'trading_desk_id', 'is_manage_user', 'date_joined', 'reset_password_url') def to_representation(self, instance, **kwargs): to_representation_dict = super(UserSerializer, self).to_representation( instance, **kwargs) user_in_groups = [] if 'user_in_groups' in to_representation_dict: for group in to_representation_dict['user_in_groups']: if group in TD_GROUPS or group in MANAGE_GROUPS: user_in_groups.append(group) to_representation_dict['user_in_groups'] = user_in_groups if 'groups' in to_representation_dict: del to_representation_dict['groups'] if 'reset_password_url' in to_representation_dict: del to_representation_dict['reset_password_url'] return to_representation_dict @transaction.atomic() def create(self, request): reset_password_url = request.pop('reset_password_url', None) if reset_password_url is None: raise serializers.ValidationError( {'reset_password_url': 'This field is required'}) if reset_password_url.find('{token}') == -1 or reset_password_url.find( '{username}') == -1: raise serializers.ValidationError({ 'reset_password_url': 'This field must contain {token} and {username} placeholders' }) groups = list( Group.objects.filter( pk__in=[int(x.pk) for x in request.pop('groups', None)])) if groups: AuditLogger.skip_next_write = True user = super(UserSerializer, self).create(request) user.date_joined = datetime.now(tzutc()) user.groups.add(*groups) else: raise serializers.ValidationError( {'groups': 'User should belong to group'}) UserProfile.objects.create(user=user) obj = TradingDesk.objects.filter( trading_desk=self.initial_data.get('trading_desk', None)) if obj.exists(): user.profile.trading_desk.add(obj.first()) else: user.save() # save auditlog raise serializers.ValidationError( {'trading_desk': 'User should belong to trading desk'}) user.save() # save auditlog reset_password_url = re.sub(r'\{token\}', user.get_reset_password_hash(), reset_password_url) reset_password_url = re.sub(r'\{username}', user.username, reset_password_url) attrs = {'user': user, 'reset_password_url': reset_password_url} send_mail(mail_to=user.username, template="new_user", attrs=attrs, mail_from="%s <*****@*****.**>" % user.trading_desk) return user @transaction.atomic() def update(self, instance, validated_data): data = deepcopy(validated_data) groups = data.pop('groups', []) AuditLogger.skip_next_write = True super(UserSerializer, self).update(instance, data) new_user_in_groups = [x.name for x in groups] old_user_in_groups = [x.name for x in instance.groups.all()] new_groups = list( Group.objects.filter(name__in=[ x for x in [x for x in new_user_in_groups if x not in old_user_in_groups] ])) old_groups = list( Group.objects.filter(name__in=[ x for x in [x for x in old_user_in_groups if x not in new_user_in_groups] ])) if old_groups: [ x.user_set.remove(instance) for x in old_groups if x.name in MANAGE_GROUPS or x.name in TD_GROUPS ] if new_groups: instance.groups.add(*new_groups) instance.save() # save auditlog return instance def is_valid(self, *args, **kwargs): valid = super(UserSerializer, self).is_valid(*args, **kwargs) instance = self.instance # username username = self.validated_data.get('username') if re.match(r'[^a-zA-Z0-9_\@\+\.\-]', username): raise serializers.ValidationError({ 'username': '******' }) user = REGISTRY['user'] user_groups = [g.name for g in user.groups.all()] user_in_groups = [] groups = self.validated_data.get('groups', None) if groups: user_in_groups = list([ x.name for x in Group.objects.filter( pk__in=[int(x.pk) for x in groups]) ]) if instance: instance_groups = [g.name for g in instance.groups.all()] instance_monarch_groups = [ g for g in instance_groups if str(g) in MANAGE_GROUPS + TD_GROUPS ] errors = {} for field in ['first_name', 'last_name']: if not self.validated_data.get(field, None) and getattr( self.instance, field): errors[field] = 'This field is required' if instance_monarch_groups and not self.validated_data.get( 'groups', None): errors['user_in_groups'] = 'This field is required' if errors: raise serializers.ValidationError(errors) if TD_ACCOUNT_MANAGER_GROUP in user_groups: for group in user_in_groups: if group not in TD_GROUPS: raise serializers.ValidationError('Available groups:%s' % TD_GROUPS.join(',')) obj = TradingDesk.objects.filter( trading_desk=self.initial_data.get('trading_desk', None)) if obj.exists(): obj = obj.first() else: raise serializers.ValidationError( {'trading_desk': 'Invalid value'}) group_list = TD_GROUPS[:] if obj.pk == MANAGE_TRADING_DESK_ID: group_list += MANAGE_GROUPS for group in user_in_groups: if group not in group_list: raise serializers.ValidationError('Available groups:%s' % ','.join(group_list)) return valid
class OrderSerializerAnti(serializers.ModelSerializer): """订单序反列化器""" goods = GoodSerializer(many=True) operators = serializers.ManyRelatedField( child_relation=serializers.PrimaryKeyRelatedField( label='所属角色', help_text='订单关联的操作员', queryset=UsersInfo.objects.all()), help_text='用户关联的角色', required=False, label='所属角色') class Meta: model = OrdersInfo fields = [ 'id', 'trans_code', 'order_status', 'freight', 'customer', 'channel', 'good_type', 'pay_type', 'operators', 'collection_money', 'v_w_rate', 'volume', 'volume_w', 'weight', 'price_w', 'number', 'transport_site', 'goods_name', 'goods_name_en', 'flight_number', 'remark_comment', 'order_time', 'receiver', 'goods', ] extra_kwargs = { 'id': { 'help_text': '订单号', 'read_only': True }, } def create(self, validated_data): request_user = self.initial_data.get('request_user') if isinstance(request_user, AnonymousUser): request_user = None validated_data['creator'] = request_user validated_data['modifier'] = validated_data.get('creator') goods = validated_data.pop('goods') operators = validated_data.pop('operators') with transaction.atomic(): order = OrdersInfo.objects.create(**validated_data) order.operators.set(operators) for good in goods: good['order_id'] = order.id good['request_user'] = request_user serializer = GoodSerializer(data=goods, many=True) serializer.is_valid(raise_exception=True) serializer.save() order.goods.set(serializer.instance) order.save() return order def update(self, instance, validated_data): with transaction.atomic(): request_user = self.initial_data.get('request_user') if isinstance(request_user, AnonymousUser): request_user = None validated_data['modifier'] = request_user GoodsInfo.objects.filter(order=instance).delete() Order2Operator.objects.filter(order=instance).delete() goods = validated_data.pop('goods') operators = validated_data.pop('operators') with transaction.atomic(): OrdersInfo.objects.filter(id=instance.id).update( **validated_data) order = OrdersInfo.objects.get(id=instance.id) order.operators.set(operators) for good in goods: good['order_id'] = order.id good['request_user'] = request_user serializer = GoodSerializer(data=goods, many=True) serializer.is_valid(raise_exception=True) serializer.save() order.goods.set(serializer.instance) order.save() return order
class ReadOnlyManyToManySerializer(serializers.ModelSerializer): rel = serializers.ManyRelatedField(read_only=True) class Meta: model = ReadOnlyManyToManyModel
class CampaignSerializer(serializers.ModelSerializer): ctr = serializers.FloatField(read_only=True) segments = serializers.ManyRelatedField( child_relation=serializers.PrimaryKeyRelatedField( queryset=Segment.objects.all()), allow_empty=True, required=False, write_only=True) def __totimestamp_posix(self, dt, epoch=datetime(1970, 1, 1)): utc_naive = dt.replace(tzinfo=None) - dt.utcoffset() return (utc_naive - epoch).total_seconds() def __update_website_and_segments_relations(self, requesting_user): # ToDo Incase of acess management, we need to change this self.fields.get( 'segments' ).child_relation = requesting_user.website.segment_set.all() def validate_scheduled_at_and_timezone(self, scheduled_at): if not scheduled_at: raise ValidationError(_("Scheduled time is required!")) # local = pytz.timezone(scheduled_at_timezone) # naive = scheduled_at # naive = naive.replace(tzinfo=None) # local_dt = local.localize(naive, is_dst=None) # scheduled_at = local_dt.astimezone(pytz.timezone(settings.TIME_ZONE)) time_right_now = pytz.timezone(settings.TIME_ZONE).localize( datetime.now()) if self.__totimestamp_posix(scheduled_at) <= self.__totimestamp_posix( time_right_now): raise ValidationError(_("Scheduled time can't be in the past!")) def validate(self, attrs): self.__update_website_and_segments_relations( self.context['request'].user) attrs = super(CampaignSerializer, self).validate(attrs) if not attrs.get('immediately', True): self.validate_scheduled_at_and_timezone( attrs.get('scheduled_at', None)) return attrs def create(self, validated_data): if validated_data.get('scheduled_at') is not None: validated_data['status'] = CampaignStatus.SCHEDULED return super(CampaignSerializer, self).create(validated_data) class Meta: model = Campaign exclude = ('auth', ) extra_kwargs = { 'ctr': { 'read_only': True }, 'status': { 'read_only': True }, 'sender': { 'read_only': True }, 'total_subs': { 'read_only': True }, 'sent_subs': { 'read_only': True }, 'clicks': { 'read_only': True }, 'revenue': { 'read_only': True }, 'impressions': { 'read_only': True }, 'closed': { 'read_only': True }, 'website': { 'read_only': True }, }