Ejemplo n.º 1
0
 def data_mart(self):
     '''
     :return: active `DataMartModel` instance from context, if `data_mart` not set, try find object by parsing request
     '''
     value = self.data_mart_pk
     if value is not None:
         key = 'pk'
         # it was a string, not an int. Try find object by `slug`
         try:
             value = int(value)
         except ValueError:
             key = 'slug'
         return get_object_or_404(DataMartModel.objects.active(), **{key: value})
     return None
Ejemplo n.º 2
0
 def data_mart(self):
     '''
     :return: active `DataMartModel` instance from `self.data_mart_id`
     '''
     value = self.data_mart_id
     if value is not None:
         key = 'pk'
         # it was a string, not an int. Try find object by `slug`
         try:
             value = int(value)
         except ValueError:
             key = 'slug'
         return get_object_or_404(DataMartModel.objects.active(), **{key: value})
     return None
Ejemplo n.º 3
0
 def tree(self, request, data_mart_pk=None, *args, **kwargs):
     if data_mart_pk is not None:
         request.GET.setdefault('parent_id', data_mart_pk)
     value = request.query_params.get('parent_id', None)
     if value is not None:
         # try find object by `slug`
         try:
             value = int(value)
         except ValueError:
             # it was a string, not an int.
             if value.lower() in ('none', 'null'):
                 queryset = DataMartModel.objects.toplevel()
             else:
                 queryset = get_object_or_404(DataMartModel.objects.all(),
                                              slug=value).get_children()
         else:
             queryset = get_object_or_404(DataMartModel.objects.all(),
                                          pk=value).get_children()
     else:
         queryset = DataMartModel.objects.toplevel()
     serializer = DataMartTreeSerializer(queryset,
                                         many=True,
                                         context={"request": request})
     return Response(serializer.data)
Ejemplo n.º 4
0
    def check_permissions(self, request):
        """
        Check if the request should be permitted.
        Raises an appropriate exception if the request is not permitted.
        """
        try:
            request.GET['_mutable'] = True
        except AttributeError:
            request.GET = request.GET.copy()
        request.GET['_data_mart'] = None

        request.GET['_data_mart_permissions'] = {
            'can_add': False,
            'can_change': False,
            'can_delete': False,
            'has_owner': False
        }

        model_class = EntityModel
        if self.action in ('retrieve', 'update', 'partial_update', 'destroy'):
            obj = self.get_object()
            model_class = obj.__class__
        elif self.action in ('create', 'list', 'bulk_update',
                             'partial_bulk_update', 'bulk_destroy'):
            value = self.kwargs.get('data_mart_pk',
                                    request.GET.get('data_mart_pk', None))
            if value is not None:
                key = 'pk'
                # it was a string, not an int. Try find object by `slug`
                try:
                    value = int(value)
                except ValueError:
                    key = 'slug'
                request.GET['_data_mart'] = data_mart = get_object_or_404(
                    DataMartModel.objects.active(), **{key: value})

                # check data mart permissions
                if self.action != 'list':
                    request.GET['_data_mart_permissions'] = data_mart_permissions = \
                        data_mart.get_permissions_from_request(request)
                    if (self.action == 'create'
                            and not data_mart_permissions['can_add']
                            or self.action in ('bulk_update',
                                               'partial_bulk_update')
                            and not data_mart_permissions['can_change']
                            or self.action == 'bulk_destroy'
                            and not data_mart_permissions['can_delete']):
                        self.permission_denied(request)

                # set model class
                model_class = data_mart.entities_model
            else:
                # в случаи списка пытаемся определить модель по полю 'entity_model' первого элемента
                if isinstance(request.data, list):
                    entity_model = request.data[0].get(
                        'entity_model', None) if len(request.data) else None
                else:
                    entity_model = request.data.get('entity_model', None)
                # пытаемся определить модель по параметру 'entity_model' словаря GET
                if entity_model is None:
                    entity_model = request.GET.get('entity_model', None)

                if entity_model is not None:
                    try:
                        model_class = apps.get_model(
                            EntityModel._meta.app_label, str(entity_model))
                    except LookupError:
                        pass

        permissions = [
            permission()
            for permission in model_class._rest_meta.permission_classes
        ]

        if not permissions:
            permissions = self.get_permissions()

        for permission in permissions:
            if not permission.has_permission(request, self):
                self.permission_denied(request,
                                       message=getattr(permission, 'message',
                                                       None))
Ejemplo n.º 5
0
    def filter_queryset(self, request, queryset, view):
        alike = self.get_alike_param(request, view)
        data_mart = request.GET['_data_mart']
        annotation_meta, aggregation_meta = None, None

        # annotation
        if view.action == 'list' or alike is not None:

            if alike is True:
                # Perform the lookup filtering.
                lookup_url_kwarg = view.lookup_url_kwarg or view.lookup_field
                assert lookup_url_kwarg in view.kwargs, (
                    'Expected view %s to be called with a URL keyword argument '
                    'named "%s". Fix your URL conf, or set the `.lookup_field` '
                    'attribute on the view correctly.' %
                    (view.__class__.__name__, lookup_url_kwarg))
                filter_kwargs = {
                    view.lookup_field: view.kwargs[lookup_url_kwarg]
                }
                obj = get_object_or_404(queryset, **filter_kwargs)
                model_class = obj.__class__
            else:
                model_class = data_mart.entities_model if data_mart is not None else queryset.model

            annotation = model_class.get_summary_annotation(request)
            if isinstance(annotation, dict):
                annotation_meta, annotate_kwargs = {}, {}
                for key, value in annotation.items():
                    if isinstance(value, (tuple, list)):
                        annotate = value[0]
                        if isinstance(annotate, BaseExpression):
                            annotate_kwargs[key] = annotate
                        n = len(value)
                        if n > 1:
                            field = value[1]
                            if isinstance(field, six.string_types):
                                field = import_string(field)()
                            name = value[2] if n > 2 else None
                            annotation_meta[key] = (annotate, field, name)
                    else:
                        assert isinstance(value, BaseExpression), (
                            "value getting from dictionary key '%s' should be instance of a class or of a subclass `BaseExpression`"
                            % key)
                        annotate_kwargs[key] = value
                if annotate_kwargs:
                    queryset = queryset.annotate(**annotate_kwargs)

        else:
            model_class = queryset.model

            if view.action in ("bulk_update", "partial_bulk_update"):
                if data_mart is not None:
                    model_class = data_mart.entities_model
                else:
                    # в случаи списка пытаемся определить модель по полю 'entity_model' первого элемента
                    if isinstance(request.data, list):
                        entity_model = request.data[0].get(
                            'entity_model', None) if len(
                                request.data) else None
                    else:
                        entity_model = request.data.get('entity_model', None)
                    # пытаемся определить модель по параметру 'entity_model' словаря GET
                    if entity_model is None:
                        entity_model = request.GET.get('entity_model', None)
                    if entity_model is not None:
                        try:
                            model_class = apps.get_model(
                                EntityModel._meta.app_label, str(entity_model))
                        except LookupError:
                            pass
                # modify queryset for `bulk_update` and `partial_bulk_update`
                queryset = model_class.objects.filter(
                    id__in=queryset.values_list('id', flat=True))

        # aggregation
        if view.action == 'list':
            aggregation = model_class.get_summary_aggregation(request)
            if isinstance(aggregation, dict):
                aggregation_meta = OrderedDict()
                for key, value in aggregation.items():
                    assert isinstance(value, (tuple, list)), (
                        "type of value getting from dictionary key '%s' should be `tuple` or `list`"
                        % key)
                    aggregate = value[0]
                    n = len(value)
                    if n > 1:
                        field = value[1]
                        if isinstance(field, six.string_types):
                            field = import_string(field)()
                        name = value[2] if n > 2 else None
                    else:
                        field, name = None, None
                    aggregation_meta[key] = (aggregate, field, name)

        request.GET.update({
            '_annotation_meta': annotation_meta,
            '_aggregation_meta': aggregation_meta,
            '_filter_queryset': queryset,
            '_alike': alike,
            '_alike_param': self.alike_param,
            '_entity_model': model_class
        })

        # select view component
        raw_view_component = request.GET.get('view_component', None)
        if raw_view_component is None:
            raw_view_component = get_data_mart_cookie_setting(
                request, "view_component")
        if raw_view_component is None:
            view_component = data_mart.view_component if data_mart is not None else None
        else:
            view_component = serializers.CharField().to_internal_value(
                raw_view_component)
        request.GET['_view_component'] = view_component
        return queryset