示例#1
0
 def _get_menu_from_autobuild(self):
     """根据模型自定义菜单"""
     export_apps = get_export_apps()
     if not export_apps:
         return success_response([])
     try:
         result, id_index = [], 0
         for app_name in export_apps:
             application = apps.get_app_config(app_name)
             for model_item in application.get_models():
                 id_index += 1
                 result.append({
                     "id": id_index,
                     "name": model_item._meta.verbose_name,
                     "icon": None,
                     "parent": None,
                     "page": "list",
                     "permission": None,
                     "model": f"{app_name}__{model_item._meta.model_name}",
                     "sequence": 0,
                     "menu": []
                 })
         return success_response(result)
     except Exception:
         return success_response([])
示例#2
0
def client_func(genericAPIView, user, app, model, func_name, params):
    """云函数, 由客户端直接调用的服务函数
        """
    func, options = find_func(app, model, func_name)
    if not func:
        raise exceptions.BusinessException(
            error_code=exceptions.FUNCTION_NOT_FOUNT,
            error_data=f'no such func: {func_name} found',
        )

    if options.get('login_required', False):
        if not user.is_authenticated:
            raise PermissionDenied()

    view_context = {'view': genericAPIView}
    params['view_context'] = view_context

    result = func(user, **params)
    # TODO:考虑函数的返回结果类型。1. 实体,2.实体列表,3.字典,4.无返回,针对不同的结果给客户端反馈
    if isinstance(result, requests.Response):
        return HttpResponse(result, result.headers.get('Content-Type', None))
    if isinstance(result, (list, dict)):
        return success_response(result)
    if isinstance(result, genericAPIView.model):
        serializer = genericAPIView.get_serializer(result)
        return success_response(serializer.data)
    return success_response()
示例#3
0
def client_update(genericAPIView, request, partial, set_data):
    """全量更新数据"""
    with transaction.atomic():
        client_user_pip.add_login_user_data(genericAPIView, set_data)
        forward_relation_hand(genericAPIView.model, set_data)

        # partial = kwargs.pop('partial', False)
        instance = genericAPIView.get_object()
        old_instance = copy(instance)

        serializer = genericAPIView.get_validate_form(genericAPIView.action)(
            instance, data=set_data, partial=partial)
        serializer.is_valid(raise_exception=True)
        instance = genericAPIView.perform_update(serializer)

        reverse_relation_hand(genericAPIView.model, set_data, instance)
        instance = genericAPIView.get_queryset().get(pk=instance.pk)

        # with transaction.atomic():
        log.debug(
            'sending Post Update signal with: model: %s, instance: %s',
            genericAPIView.model,
            instance,
        )
        post_bsm_create.send(
            sender=genericAPIView.model,
            instance=instance,
            create=False,
            request=genericAPIView.request,
            old_instance=old_instance,
        )

        serializer = genericAPIView.get_serializer(
            genericAPIView.get_queryset().get(pk=instance.pk))
        return success_response(serializer.data)
示例#4
0
 def _get_menu_from_database(self):
     """从数据库中获取菜单"""
     user = self.request.user
     # permissions = self.request.user.get_all_permissions()
     # permission_filter = (Q(permission=None) | Q(permission='') | Q(permission__in=permissions))
     menus =  Menu.objects.prefetch_related('parent').order_by('sequence','id') if user.is_superuser else \
           Menu.objects.filter(Q(groups__in=self.request.user.groups.all()) | Q(groups__isnull=True)).prefetch_related('parent').order_by('sequence','id')
     fields = {field.name
               for field in Menu._meta.fields
               } - {'id', 'parent', 'permission', 'name'}
     menus_map = {
         menu.id: dict({field: getattr(menu, field)
                        for field in fields}, **{
                            'name': menu.display_name,
                            'parent_id': menu.parent_id,
                            'children': []
                        })
         for menu in menus
     }
     for _, menu in menus_map.items():
         parent_id = menu['parent_id']
         if parent_id and parent_id in menus_map:
             menus_map[parent_id]['children'].append(menu)
     menus_data = [
         m for _, m in menus_map.items() if not m.get('parent_id')
     ]
     return success_response(menus_data)
示例#5
0
def update_sort(genericAPIView, request, data):
    if data.get('dragId') == data.get('hoverId'):
        return
    instance = genericAPIView.model
    admin = genericAPIView.get_bsm_model_admin()
    sort_key = admin.sort_key
    from django.db.models import F, Q

    with transaction.atomic():
        dragItem = instance.objects.filter(id=data['dragId']).first()
        hoverItem = instance.objects.filter(id=data['hoverId']).first()
        dragIndex = getattr(dragItem, sort_key)
        hoveIndex = getattr(hoverItem, sort_key)
        isDownward = dragIndex < hoveIndex or (
            dragIndex == hoveIndex and dragItem.id < hoverItem.id
        )
        instance.objects.filter(id=data['dragId']).update(
            **{'parent': hoverItem.parent, sort_key: hoveIndex + 1}
        )

        instance.objects.filter(
            Q(parent=hoverItem.parent),
            ~Q(id=dragItem.id),
            Q(**{f'{sort_key}__gt': hoveIndex}),
        ).update(**{f'{sort_key}': F(f'{sort_key}') + 2})
        up = Q(id__gt=hoverItem.id) if isDownward else Q(id__gte=hoverItem.id)
        instance.objects.filter(
            Q(parent=hoverItem.parent),
            ~Q(id=dragItem.id),
            Q(**{f'{sort_key}': hoveIndex}),
            up,
        ).update(**{f'{sort_key}': F(f'{sort_key}') + 2})
    return success_response(instance.objects.all().values())
示例#6
0
def delete_by_conditon(genericAPIView):
    """按查询条件删除"""
    queryset = genericAPIView.filter_queryset(genericAPIView.get_queryset())
    deleted, rows_count = queryset.delete()
    result = {'deleted': deleted}

    return success_response(result)
示例#7
0
    def token(self, request, *args, **kwargs):
        """
        ## 生成对应的上传签名

        **参数放在 query string 中,形式如 ?service=aliyun**

        当前的服务只支持 (aliyun, 阿里云)

        ### Returns

        #### 阿里云的返回数据结构如下:

        ```
        {
            "error_code": "0",
            "error_message": "",
            "result": {
                "accessid": "LTAIudMj4IZMpCCn",
                "host": "speedapi.oss-cn-shanghai.aliyuncs.com",
                "policy": "eyJleHBpcmF0aW9uIjogIjIwMTgV5IiwgIm1lZGlhLyJdXX0=",
                "signature": "9aOOMFzwwVQl0u/sFgdLKRSyeIw=",
                "expire": 1539770693,
                "dir": "media/"
            }
        }
        ```

        #### 腾讯云 COS 返回的数据结构如下
        {
            'startTime': 1592561936
            'expiredTime': 1592561966,
            'expiration': '2020-06-19T10:19:26Z',
            'requestId': '4332ced3-50a7-48fb-a35a-cb9efcec95d9',
            'bucket': 'test-20188932',
            'region': 'ap-guangzhou',
            'credentials': {
                'sessionToken': 'kg1Mg_UmDtAJ3wQA',
                'tmpSecretId': 'AKIDy_RmF9qEg1geYsrJ_UwR4WWYcDGM2iy71R',
                'tmpSecretKey': 'Q5FPMVsD='
            },
        }
        """
        service = request.query_params.get('service',
                                           site_setting['upload_provider'])
        result = {'provider': None}
        if service in ['aliyun', 'oss']:
            result = aliyun.get_token()
            result['provider'] = 'oss'
        elif service in ['tencent', 'cos']:
            result = tencent.post_object_token()
            result['provider'] = 'cos'
        elif service == 'file_storage':
            result = {
                'provider': 'file_storage',
                'policy': '',
                'dir': '',
                'host': '/basebone/storage/upload'
            }
        return success_response(result)
示例#8
0
def destroy(genericAPIView, request, scope=''):
    """删除数据"""
    instance = genericAPIView.get_object()
    old_instance = copy(instance)
    genericAPIView.perform_destroy(instance)
    post_bsm_delete.send(
        sender=genericAPIView.model, instance=old_instance, request=genericAPIView.request, scope=scope
    )
    return success_response()
示例#9
0
    def get_userinfo(self, request, *args, **kwargs):
        """
        ## 检测是否是否登录

        如果用户已登录,则直接返回此登录用户的数据结构
        """
        serializer = self.get_serializer(request.user)
        result = {}
        result.update(serializer.data)
        result['permissions'] = request.user.get_all_permissions()
        return success_response(result)
示例#10
0
    def _get_menu_from_custom(self):
        """从自定义的菜单配置中获取菜单"""
        menu_module = module.get_bsm_global_module(
            module.BSM_GLOBAL_MODULE_MENU)
        result = getattr(menu_module, module.BSM_GLOBAL_MODULE_MENU_MANAGE,
                         None)

        by_role = getattr(settings, 'BSM_MANAGE_MENU_BY_ROLE', False)
        if not by_role:
            return success_response(result['default'])
        else:
            groups = {item.name for item in self.request.user.groups.all()}
            if not groups:
                return success_response([])

            for item in groups:
                if item in result:
                    return success_response(result[item])

        return success_response([])
示例#11
0
def manage_create(genericAPIView, request, set_data):
    """
        这里校验表单和序列化类分开创建

        原因:序列化类有可能嵌套
        """
    many = isinstance(set_data, list)
    with transaction.atomic():
        forward_relation_hand(genericAPIView.model, set_data)
        serializer = genericAPIView.get_validate_form(genericAPIView.action)(
            data=set_data,
            context=genericAPIView.get_serializer_context(),
            many=many)
        serializer.is_valid(raise_exception=True)
        instance = genericAPIView.perform_create(serializer)

        if many:
            # 如果是批量插入,则直接返回
            return success_response()

        # 如果有联合查询,单个对象创建后并没有联合查询
        instance = genericAPIView.get_queryset().filter(pk=instance.pk).first()
        serializer = genericAPIView.get_serializer(instance)
        reverse_relation_hand(genericAPIView.model,
                              set_data,
                              instance,
                              detail=False)

        log.debug(
            'sending Post Save signal with: model: %s, instance: %s',
            genericAPIView.model,
            instance,
        )
        post_bsm_create.send(sender=genericAPIView.model,
                             instance=instance,
                             create=True,
                             request=genericAPIView.request,
                             old_instance=None,
                             scope='admin')
    return success_response(serializer.data)
示例#12
0
    def batch(self, request, app, model, **kwargs):
        """
        ## 批量操作

        ```python
        {action: 动作, data: 主键的列表}
        ```
        """
        serializer = batch_actions.BatchActionForm(
            data=request.data, context=self.get_serializer_context())
        serializer.is_valid(raise_exception=True)
        serializer.handle()
        return success_response()
示例#13
0
def manage_func(genericAPIView, user, app, model, func_name, params):
    """云函数, 由客户端直接调用的服务函数
        """
    # import ipdb; ipdb.set_trace()
    func, options = find_func(app, model, func_name)
    if not func:
        raise exceptions.BusinessException(
            error_code=exceptions.FUNCTION_NOT_FOUNT,
            error_data=f'no such func: {func_name} found',
        )
    if options.get('login_required', False):
        if not user.is_authenticated:
            raise PermissionDenied()
    if options.get('staff_required', False):
        if not user.is_staff:
            raise PermissionDenied()
    if options.get('superuser_required', False):
        if not user.is_superuser:
            raise PermissionDenied()

    view_context = {'view': genericAPIView}
    params['view_context'] = view_context
    result = func(user, **params)

    # TODO:考虑函数的返回结果类型。1. 实体,2.实体列表,3.字典,4.无返回,针对不同的结果给客户端反馈
    if isinstance(result, requests.Response):
        response = HttpResponse(result, result.headers.get('Content-Type', None))
        if 'Content-disposition' in result.headers:
            response['Content-disposition'] = result.headers.get('Content-disposition')
        return response
    if (
        isinstance(result, list)
        or isinstance(result, dict)
        or isinstance(result, str)
        or isinstance(result, bytes)
    ):
        return success_response(result)
    return success_response()
示例#14
0
def display(genericAPIView, display_fields):
    """查询操作,取名display,避免跟列表list冲突"""
    queryset = genericAPIView.filter_queryset(genericAPIView.get_queryset())

    page = genericAPIView.paginate_queryset(queryset)
    if page is not None:
        """分页查询"""
        serializer = genericAPIView.get_serializer(page, many=True)
        result = filter_display_fields(serializer.data, display_fields)
        response = genericAPIView.get_paginated_response(result)
        result = response.data
    else:
        serializer = genericAPIView.get_serializer(queryset, many=True)
        result = filter_display_fields(serializer.data, display_fields)
    return success_response(result)
示例#15
0
 def get_all(self, request, *args, **kargs):
     """获取所有的客户端配置,包括schema, admin
     """
     self._load_bsm_admin_module()
     data = {
         'schemas': get_app_field_schema(),
         'admins': get_app_admin_config()
     }
     json_object_schemas, json_array_item_schemas = get_app_json_field_schema(
     )
     json_admin_configs = get_json_field_admin_config(
         json_object_schemas, json_array_item_schemas)
     data['schemas'].update(json_object_schemas)
     data['schemas'].update(json_array_item_schemas)
     data['admins'].update(json_admin_configs)
     return success_response(data)
示例#16
0
def upload(request):
    key, policy, file = request.data['key'], request.data['policy'], request.data['file']
    storage_path = site_setting['storage_path']
    if not storage_path:
        raise BusinessException('storage support not enabled')
    file_path = Path(storage_path).joinpath(key)
    if not is_relative_to(file_path, storage_path):
        raise BusinessException('invalid file key: %s' % key)
    dirname = file_path.parent
    if not dirname.exists():
        dirname.mkdir(parents=True)
    elif not dirname.is_dir():
        raise BusinessException('dir exists: %s' % os.path.dirname(key))
    elif file_path.exists():
        raise BusinessException('file already exists: %s' % key)
    with file_path.open('wb+') as f:
        for chunk in file.chunks():
            f.write(chunk)
    return success_response()
示例#17
0
    def login(self, request, *args, **kwargs):
        """
        ## 用户登录

        ```
        Params:
            username string 用户名
            password string 用户密码

        Returns:
            object 用户数据结构
        ```
        """
        serializer = forms.LoginForm(data=request.data,
                                     context=self.get_serializer_context())
        serializer.is_valid(raise_exception=True)

        instance = serializer.save()
        serializer = self.get_serializer(instance)
        return success_response(serializer.data)
示例#18
0
def manage_update(genericAPIView, request, partial, set_data):
    """全量更新数据"""
    print('进入全量更新了吗?')
    with transaction.atomic():
        forward_relation_hand(genericAPIView.model, set_data)

        # partial = kwargs.pop('partial', False)
        instance = genericAPIView.get_object()
        old_instance = copy(instance)
        serializer = genericAPIView.get_validate_form(genericAPIView.action)(
            instance,
            data=set_data,
            partial=partial,
            context=genericAPIView.get_serializer_context(),
        )
        serializer.is_valid(raise_exception=True)

        instance = genericAPIView.perform_update(serializer)
        serializer = genericAPIView.get_serializer(instance)

        if getattr(instance, '_prefetched_objects_cache', None):
            instance._prefetched_objects_cache = {}

        reverse_relation_hand(genericAPIView.model, set_data, instance)

    with transaction.atomic():
        log.debug(
            'sending Post Update signal with: model: %s, instance: %s',
            genericAPIView.model,
            instance,
        )
        post_bsm_create.send(
            sender=genericAPIView.model,
            instance=instance,
            create=False,
            old_instance=old_instance,
            request=genericAPIView.request,
            scope='admin'
        )
    return success_response(serializer.data)
示例#19
0
    def get_manage_menu(self, request, *args, **kwargs):
        """获取管理端的菜单配置"""
        if hasattr(settings, 'ADMIN_MENUS'):
            group_names = self.request.user.groups.values_list('name',
                                                               flat=True)
            group_names = set(group_names)

            def map_menus(menus):
                return [{
                    **m, 'children': map_menus(m.get('children', []))
                } for m in menus
                        if 'groups' not in m or self.request.user.is_superuser
                        or set(m['groups']) & group_names]

            return success_response(map_menus(settings.ADMIN_MENUS))

        menutype = request.query_params.get('menutype', 'database')
        if menutype == 'database':
            return self._get_menu_from_database()
        if menutype == 'custom':
            return self._get_menu_from_custom()
        if menutype == 'autobuild':
            return self._get_menu_from_autobuild()
示例#20
0
def client_create(genericAPIView, request, set_data):
    """
        这里校验表单和序列化类分开创建

        原因:序列化类有可能嵌套
        """

    with transaction.atomic():
        client_user_pip.add_login_user_data(genericAPIView, set_data)
        forward_relation_hand(genericAPIView.model, set_data)
        serializer = genericAPIView.get_validate_form(genericAPIView.action)(
            data=set_data
        )
        serializer.is_valid(raise_exception=True)
        instance = genericAPIView.perform_create(serializer)
        reverse_relation_hand(genericAPIView.model, set_data, instance, detail=False)
        instance = genericAPIView.get_queryset().get(pk=instance.pk)

        # with transaction.atomic():
        log.debug(
            'sending Post Save signal with: model: %s, instance: %s',
            genericAPIView.model,
            instance,
        )
        post_bsm_create.send(
            sender=genericAPIView.model,
            instance=instance,
            create=True,
            request=genericAPIView.request,
            old_instance=None,
            scope='client',
        )
        # 如果有联合查询,单个对象创建后并没有联合查询, 所以要多查一次?
        serializer = genericAPIView.get_serializer(
            genericAPIView.get_queryset().get(pk=instance.pk)
        )
        return success_response(serializer.data)
示例#21
0
 def permissions(self, request, *args, **kwargs):
     """获取当前用户的权限
     """
     return success_response(request.user.get_all_permissions())
示例#22
0
def update_by_conditon(genericAPIView, set_fields):
    queryset = genericAPIView.filter_queryset(genericAPIView.get_queryset())
    count = queryset.update(**set_fields)
    result = {'count': count}
    return success_response(result)
示例#23
0
 def get_admin(self, request, *args, **kwargs):
     self._load_bsm_admin_module()
     """获取 admin 配置"""
     data = get_app_admin_config()
     return success_response(data)
示例#24
0
 def admin(self, request, model_name):
     model, created = Admin.objects.get_or_create(model=model_name)
     model.config = dict(request.data)
     model.save()
     return success_response()
示例#25
0
 def get_web_settins(self, request, *args, **kargs):
     settings = get_settins()
     return success_response(settings)
示例#26
0
def retrieve(genericAPIView, display_fields):
    """获取数据详情"""
    instance = genericAPIView.get_object()
    serializer = genericAPIView.get_serializer(instance)
    result = filter_display_fields(serializer.data, display_fields)
    return success_response(result)
示例#27
0
 def get_setting_config(self, request, *args, **kargs):
     settings = get_setting_config()
     return success_response(settings)
示例#28
0
def block_view(request, block_id):
    block = Block.objects.get(id=block_id)
    data = None
    if block.component in component_resolver_map:
        data = component_resolver_map[block.component](block)
    return success_response(data)
示例#29
0
def move(request, block_id):
    parent = request.data.get('parent', None)
    index = request.data['index']
    services.move(block_id, parent, index)
    return success_response()
示例#30
0
 def logout(self, request, *args, **kwargs):
     """退出登录"""
     logout(request)
     return success_response()