Esempio n. 1
0
def insert_user_info(data, model, user_id, action):
    if not isinstance(data, dict):
        return None, None
    creator_field = get_gmeta_config_by_key(model, gmeta.GMETA_CREATOR_FIELD)
    updater_field = get_gmeta_config_by_key(
        model, gmeta.GMETA_UPDATER_FIELD) or getattr(
            model, admin.BSM_AUTH_FILTER_FIELD, None)
    if updater_field:
        data[updater_field] = user_id
    if action == 'create' and creator_field and creator_field != updater_field:
        data[creator_field] = user_id
    return creator_field, updater_field
Esempio n. 2
0
    def get_queryset(self):
        """动态的计算结果集

        - 如果是展开字段,这里做好是否关联查询
        """
        managers = get_gmeta_config_by_key(self.model, gmeta.GMETA_MANAGERS)
        if managers and 'client_api' in managers:
            objects = getattr(self.model, managers['client_api'],
                              self.model.objects)
        else:
            objects = self.model.objects

        queryset = objects.all()

        expand_fields = self.expand_fields
        if expand_fields:
            expand_fields = self.translate_expand_fields(expand_fields)
            field_list = [item.replace('.', '__') for item in expand_fields]
            queryset = queryset.prefetch_related(*field_list)

        filter_fields = set()

        def add_filter_fields(cons):
            for con in cons:
                if 'field' in con:
                    filter_fields.add(con['field'])
                if 'children' in con:
                    add_filter_fields(con['children'])

        add_filter_fields(self.request.data.get(const.FILTER_CONDITIONS, []))
        queryset = queryset_utils.annotate(queryset,
                                           filter_fields,
                                           context={'user': self.request.user})

        return self._get_queryset(queryset)
Esempio n. 3
0
def get_export_config_by_key(model, key, export_config=None):
    """
    获取指定键的导出配置数据
    """
    value = None
    if isinstance(export_config, dict):
        value = export_config.get(key)
    if not value:
        value = get_gmeta_config_by_key(model, key)
    return value
Esempio n. 4
0
    def check_permissions(self, request):
        """校验权限"""
        if not hasattr(self, 'model'):
            return False

        action_skip = get_gmeta_config_by_key(
            self.model, gmeta.GMETA_CLIENT_API_PERMISSION_SKIP)
        if isinstance(action_skip,
                      (tuple, list)) and self.action in action_skip:
            return True
        super().check_permissions(request)
Esempio n. 5
0
    def get_queryset_by_filter_user(self, queryset):
        """通过用户过滤对应的数据集

        - 如果用户是超级用户,则不做任何过滤
        - 如果用户是普通用户,则客户端筛选的模型有引用到了用户模型,则过滤对应的数据集
        """
        user = self.request.user
        if user and user.is_staff and user.is_superuser:
            return queryset

        # 检测模型中是否有字段引用了用户模型
        has_user_field = meta.get_related_model_field(self.model,
                                                      get_user_model())
        if has_user_field:
            # 如果有,则读取模型中 GMeta 中的配置
            # FIXME: 注意,这里和管理端的处理逻辑暂时是不同的
            user_field_name = get_gmeta_config_by_key(
                self.model, gmeta.GMETA_CLIENT_USER_FIELD)
            filter_by_login_user = get_gmeta_config_by_key(
                self.model, gmeta.GMETA_CLIENT_FILTER_BY_LOGIN_USER)
            if user_field_name and filter_by_login_user:
                return queryset.filter(**{user_field_name: user})
        return queryset
Esempio n. 6
0
def create_form_class(model, exclude_fields=None, **kwargs):
    """构建序列化类"""

    def __init__(self, *args, **kwargs):
        """
        重置导出的字段映射,因为类似 BooleanField 字段,显示为中文会比较友好
        """
        self.serializer_field_mapping[JSONField] = drf_field.JSONField
        self.serializer_field_mapping[OriginJSONField] = DrfJSONField
        super(serializers.ModelSerializer, self).__init__(*args, **kwargs)

    def update(self, instance, validated_data):
        raise_errors_on_nested_writes('update', self, validated_data)
        info = model_meta.get_field_info(instance)

        for attr, value in validated_data.items():
            if attr in info.relations and info.relations[attr].to_many:
                field = getattr(instance, attr)
                if rfu_modes.append and attr in rfu_modes.append:
                    field.add(value)
                else:
                    field.set(value)
            else:
                setattr(instance, attr, value)
        instance.save()

        return instance

    attrs = {
        'Meta': create_meta_class(model, exclude_fields=None), 
        '__init__': __init__,
        'update': update
    }
    attrs.update(kwargs)

    class_name = f'{model}ModelSerializer'

    # 创建表单级的校验方法
    validators = get_gmeta_config_by_key(model, gmeta.GMETA_OBJECT_VALIDATORS)
    if validators:
        attrs['validate'] = get_validate(validators)
        # MethodType(get_validate(validators), cls)
    return type(class_name, (serializers.ModelSerializer,), attrs)
Esempio n. 7
0
def create_serializer_class(
    model,
    exclude_fields=None,
    tree_structure=None,
    action=None,
    end_slug=None,
    attrs=None,
    display_fields=None,
    allow_one_to_one=False,
):
    """构建序列化类

    Params:
        tree_structure 元组 admin 中做对应配置
    """
    if attrs is None:
        attrs = {}

    def __init__(self, *args, **kwargs):
        """
        重置导出的字段映射,因为类似 BooleanField 字段,显示为中文会比较友好
        """
        self.serializer_field_mapping[JSONField] = drf_field.JSONField
        self.serializer_field_mapping[OriginJSONField] = DrfJSONField
        if self.action == 'export_file':
            self.serializer_field_mapping[
                models.BooleanField] = drf_field.ExportBooleanField
            self.serializer_field_mapping[
                models.DateTimeField] = drf_field.ExportDateTimeField
            self.serializer_choice_field = drf_field.ExportChoiceField
        else:
            # 恢复为原来的字段类型映射,因为上面改了类的变量属性值
            self.serializer_field_mapping[
                models.BooleanField] = fields.BooleanField
            self.serializer_field_mapping[
                models.DateTimeField] = fields.DateTimeField
            self.serializer_choice_field = fields.ChoiceField

        super(CustomModelSerializer, self).__init__(*args, **kwargs)

    extra_fields = list(attrs.keys())
    new_attr = {}
    # 动态构建树形结构的字段
    if tree_structure:
        extra_fields.append(tree_structure[1])
        new_attr[tree_structure[1]] = RecursiveSerializer(many=True)

    # 构建计算属性字段
    computed_fields = get_gmeta_config_by_key(model,
                                              gmeta.GMETA_COMPUTED_FIELDS)
    if computed_fields:
        extra_fields += [f['name'] for f in computed_fields]
        for field in computed_fields:
            name = field['name']
            field_type = field['type']

            # 如果是导出,则使用导出的字段序列化类
            if (action == EXPORT_FILE_ACTION
                    and field_type in ExportFieldTypeSerializerMap):
                new_attr[name] = ExportFieldTypeSerializerMap[field_type](
                    read_only=True)
            else:
                new_attr[name] = ComputedFieldTypeSerializerMap[field_type](
                    read_only=True)

    # 构建annotate算属性字段
    annotated_fields = get_attr_in_gmeta_class(model,
                                               gmeta.GMETA_ANNOTATED_FIELDS,
                                               {})
    if annotated_fields:
        extra_fields += annotated_fields.keys()
        for name, field in annotated_fields.items():
            new_attr[name] = ComputedFieldTypeSerializerMap[field['type']](
                read_only=True)

    class_name = f'{model.__name__}ModelSerializer'
    return type(
        class_name,
        (BaseModelSerializerMixin, CustomModelSerializer),
        {
            'Meta':
            create_meta_class(
                model,
                exclude_fields=exclude_fields,
                extra_fields=extra_fields,
                display_fields=display_fields,
                action=action,
                allow_one_to_one=allow_one_to_one,
            ),
            'action':
            action,
            'basebone_model':
            model,
            'basebone_end_slug':
            end_slug,
            '__init__':
            __init__,
            **new_attr,
            **attrs,
        },
    )
Esempio n. 8
0
def insert_user_to_data(model, user, data):
    """插入用户到数据中"""

    # 第一部分,先检测模型中的字段是否有引用用户模型,如果有,则注入用户数据
    auth_user_field = None

    # 检测模型中是否有字段引用了用户模型
    has_user_field = meta.get_related_model_field(model, get_user_model())
    if has_user_field:
        field_name = get_gmeta_config_by_key(model, gmeta.GMETA_CLIENT_USER_FIELD)
        if field_name:
            auth_user_field = field_name
            # 如果用户数据中没有传递用户的数据,则进行插入
            if field_name not in data:
                data[field_name] = user.id

    relation_fields = meta.get_all_relation_fields(model)
    if relation_fields:
        for item in relation_fields:
            if item.name not in data or item.name == auth_user_field:
                # 如果字段没有在 data 中或者字段名称和 auth_user_field 相同,则不做任何处理
                continue

            value = data[item.name]

            if meta.check_field_is_reverse(item):
                # FIXME:  当前反向字段使用的是列表数据结构
                if not value or not isinstance(value, list):
                    continue

                has_user_field = meta.get_related_model_field(
                    item.related_model, get_user_model()
                )
                if has_user_field:
                    field_name = get_gmeta_config_by_key(
                        item.related_model, gmeta.GMETA_CLIENT_USER_FIELD
                    )
                    if field_name:
                        for reverse_item in value:
                            if isinstance(reverse_item, dict):
                                # 如果用户数据中没有传递用户的数据,则进行插入
                                if field_name not in reverse_item:
                                    reverse_item[field_name] = user.id
            else:
                # 这里说明是正向字段
                if item.many_to_many:
                    # 说明是多对多字段
                    if not value or not isinstance(value, list):
                        continue

                    has_user_field = meta.get_related_model_field(
                        item.related_model, get_user_model()
                    )
                    if has_user_field:
                        field_name = get_gmeta_config_by_key(
                            item.related_model, gmeta.GMETA_CLIENT_USER_FIELD
                        )
                        if field_name:
                            for child_item in value:
                                if isinstance(child_item, dict):
                                    # 如果用户数据中没有传递用户的数据,则进行插入
                                    if field_name not in child_item:
                                        child_item[field_name] = user.id
                else:
                    # 使用字典数据结构
                    if isinstance(value, dict):
                        has_user_field = meta.get_related_model_field(
                            item.related_model, get_user_model()
                        )
                        if has_user_field:
                            field_name = get_gmeta_config_by_key(
                                item.related_model, gmeta.GMETA_CLIENT_USER_FIELD
                            )
                            if field_name:
                                # 如果用户数据中没有传递用户的数据,则进行插入
                                if field_name not in value:
                                    value[field_name] = user