Exemple #1
0
    def mail_scene(objects: QuerySet,
                   field: Optional[str] = None,
                   value=None,
                   ctype=None,
                   object_pk=None):
        tr: TestRun = objects[0].run
        # scence_templates format:
        # template, subject, context
        tcrs = (objects.select_related('case', 'assignee').only(
            'case__summary', 'assignee__username').order_by('pk'))
        tcr: TestCaseRun
        scence_templates = {
            'assignee': {
                'template_name': 'mail/change_case_run_assignee.txt',
                'subject': f'Assignee of run {tr.pk} has been changed',
                'recipients': tr.get_notification_recipients(),
                'context': {
                    'run_id':
                    tr.pk,
                    'summary':
                    tr.summary,
                    'full_url':
                    tr.get_full_url(),
                    'test_case_runs': [{
                        'pk': tcr.pk,
                        'case_summary': tcr.case.summary,
                        'assignee': tcr.assignee.username,
                    } for tcr in tcrs]
                }
            }
        }

        return scence_templates.get(field)
Exemple #2
0
    def decorate_queryset(
        cls,
        feature_type: FeatureType,
        queryset: models.QuerySet,
        output_crs: CRS,
        **params,
    ) -> models.QuerySet:
        """Make sure relations are included with select-related to avoid N-queries.
        Using prefetch_related() isn't possible with .iterator().
        """
        xsd_type: XsdComplexType = feature_type.xsd_type

        # Take all relations that are expanded to complex elements,
        # and all relations that are fetched for flattened elements.
        related = {
            xsd_element.orm_path
            for xsd_element in xsd_type.complex_elements
            if not xsd_element.is_many
        } | {
            xsd_element.orm_relation[0]
            for xsd_element in xsd_type.flattened_elements
            if not xsd_element.is_many
        }
        if related:
            queryset = queryset.select_related(*related)

        return queryset
Exemple #3
0
    def mail_scene(objects: QuerySet,
                   field: Optional[str] = None,
                   value=None,
                   ctype=None,
                   object_pk=None):
        tcs = (objects.select_related('reviewer').only(
            'summary', 'reviewer__email').order_by('pk'))
        tc: TestCase
        scence_templates = {
            'reviewer': {
                'template_name':
                'mail/change_case_reviewer.txt',
                'subject':
                'You have been the reviewer of cases',
                'recipients':
                list(set(tcs.values_list('reviewer__email', flat=True))),
                'context': {
                    'test_cases': [{
                        'pk': tc.pk,
                        'summary': tc.summary,
                        'full_url': tc.get_full_url()
                    } for tc in tcs],
                }
            }
        }

        return scence_templates.get(field)
Exemple #4
0
def optimize_query(query: QuerySet, meta: FieldMeta) -> QuerySet:
    model = query.model
    only_cols = get_only_cols(model, meta.sections)
    select_related_cols, prefetchs = get_related_cols(model, meta.sub_fields)
    if only_cols:
        query = query.only(*only_cols)
    if select_related_cols:
        query = query.select_related(*select_related_cols)
    if prefetchs:
        query = query.prefetch_related(*prefetchs)
    return query
    def filter_queryset(self, request: Request, queryset: QuerySet,
                        view: GenericViewSet):
        if (not issubclass(view.get_serializer_class(),
                           FlexFieldsSerializerMixin)
                or request.method != "GET"):
            return queryset

        auto_remove_fields_from_query = getattr(
            view, "auto_remove_fields_from_query", True)
        auto_select_related_on_query = getattr(view,
                                               "auto_select_related_on_query",
                                               True)
        required_query_fields = list(getattr(view, "required_query_fields",
                                             []))

        serializer = view.get_serializer(  # type: FlexFieldsSerializerMixin
            context=view.get_serializer_context())

        serializer.apply_flex_fields()

        model_fields = [
            self._get_field(field.source, queryset.model)
            for field in serializer.fields.values()
            if self._get_field(field.source, queryset.model)
        ]

        nested_model_fields = [
            self._get_field(field.source, queryset.model)
            for field in serializer.fields.values()
            if self._get_field(field.source, queryset.model)
            and field.field_name in serializer.expanded_fields
        ]

        if auto_remove_fields_from_query:
            queryset = queryset.only(*(required_query_fields + [
                model_field.name for model_field in model_fields
                if not model_field.is_relation or model_field.many_to_one
            ]))

        if auto_select_related_on_query and nested_model_fields:
            queryset = queryset.select_related(
                *(model_field.name for model_field in nested_model_fields
                  if model_field.is_relation and model_field.many_to_one))

            queryset = queryset.prefetch_related(
                *(model_field.name for model_field in nested_model_fields
                  if model_field.is_relation and not model_field.many_to_one))

        return queryset
Exemple #6
0
 def build_queryset(self, queryset: models.QuerySet) -> models.QuerySet:
     if self.query:
         queryset = self.query.apply_to_queryset(queryset)
     if self.order_by:
         queryset = queryset.order_by(*self.order_by)
     if self.distinct:
         queryset = queryset.distinct(*self.distinct)
     if self.prefetch_trees:
         select_related = []
         for prefetch_tree in self.prefetch_trees:
             tree_select_related = self._flatten_prefetch_tree(
                 prefetch_tree=prefetch_tree)
             if tree_select_related is not None:
                 select_related += tree_select_related
         queryset = queryset.select_related(
             *[sr for sr in select_related if sr is not None])
     return queryset
 def setup_eager_loading(cls, queryset: QuerySet):
     return queryset.select_related('service', 'user_profile',
                                    'user_profile__account')
Exemple #8
0
 def _optimize_query(
         self,
         qs: QuerySet,
         blocked_user: Optional[List[Tuple[int, Optional[int]]]] = None):
     return qs.select_related()
Exemple #9
0
 def select_url_needed_staff(cls, qs: QuerySet) -> QuerySet:
     return qs.select_related('brand', 'category__parent',
                              'category__parent__parent',
                              'category__parent__parent__parent',
                              'category__parent__parent__parent__parent')
 def setup_eager_loading(queryset: QuerySet):
     return queryset.select_related('stream')
Exemple #11
0
    def bulk_updater(self,
                     queryset: QuerySet,
                     update_fields: Optional[Set[str]] = None,
                     return_pks: bool = False,
                     local_only: bool = False,
                     querysize: Optional[int] = None) -> Optional[Set[Any]]:
        """
        Update local computed fields and descent in the dependency tree by calling
        ``update_dependent`` for dependent models.

        This method does the local field updates on `queryset`:

            - eval local `MRO` of computed fields
            - expand `update_fields`
            - apply optional `select_related` and `prefetch_related` rules to `queryset`
            - walk all records and recalculate fields in `update_fields`
            - aggregate changeset and save as batched `bulk_update` to the database

        By default this method triggers the update of dependent models by calling
        ``update_dependent`` with `update_fields` (next level of tree traversal).
        This can be suppressed by setting `local_only=True`.

        If `return_pks` is set, the method returns a set of altered pks of `queryset`.
        """
        model: Type[Model] = queryset.model

        # distinct issue workaround
        # the workaround is needed for already sliced/distinct querysets coming from outside
        # TODO: distinct is a major query perf smell, and is in fact only needed on back relations
        #       may need some rework in _querysets_for_update
        #       ideally we find a way to avoid it for forward relations
        #       also see #101
        if queryset.query.can_filter() and not queryset.query.distinct_fields:
            queryset = queryset.distinct()
        else:
            queryset = model.objects.filter(
                pk__in=subquery_pk(queryset, queryset.db))

        # correct update_fields by local mro
        mro = self.get_local_mro(model, update_fields)
        fields: Any = set(
            mro)  # FIXME: narrow type once issue in django-stubs is resolved
        if update_fields:
            update_fields.update(fields)

        select = self.get_select_related(model, fields)
        prefetch = self.get_prefetch_related(model, fields)
        if select:
            queryset = queryset.select_related(*select)
        if prefetch:
            queryset = queryset.prefetch_related(*prefetch)

        pks = []
        if fields:
            q_size = self.get_querysize(model, fields, querysize)
            change: List[Model] = []
            for elem in slice_iterator(queryset, q_size):
                # note on the loop: while it is technically not needed to batch things here,
                # we still prebatch to not cause memory issues for very big querysets
                has_changed = False
                for comp_field in mro:
                    new_value = self._compute(elem, model, comp_field)
                    if new_value != getattr(elem, comp_field):
                        has_changed = True
                        setattr(elem, comp_field, new_value)
                if has_changed:
                    change.append(elem)
                    pks.append(elem.pk)
                if len(change) >= self._batchsize:
                    self._update(queryset, change, fields)
                    change = []
            if change:
                self._update(queryset, change, fields)

        # trigger dependent comp field updates from changed records
        # other than before we exit the update tree early, if we have no changes at all
        # also cuts the update tree for recursive deps (tree-like)
        if not local_only and pks:
            self.update_dependent(model.objects.filter(pk__in=pks),
                                  model,
                                  fields,
                                  update_local=False)
        return set(pks) if return_pks else None