Hello,

Below are 2 feature requests :
- the first would just be to add a constant object for ignoring some filters,
to avoid lists of "if ... is not None: q = q.filter(...)" like I must
do right now,
q = q.filter(id_in=[1,2,3]) filters something
q = q.filter(id_in=IGNORE_FILTER) does not filter
- the second would be to have "in-place" variants of filter and exclude, like :
q.filter_in_place(id_lt=5)
instead of
q = q.filter(id_lt=5)
Maybe other people asked for one or both of these features before,
but I did check the search here :
https://code.djangoproject.com/search
and also the archive here :
https://groups.google.com/g/django-developers/search?q=ignore%20filter
etc.
and found nothing related.

I proposed this morning the following class with better example at my
team at work,
but the decision was took that we stay on bare Django.
Nevertheless, some of my teammates agreed that the IGNORE_FILTER
feature was nice.

class EnhancedQuerySet:
    """
    Extends the functionalities of Django QuerySet
    Example:
    - before:
    def some_function(
        fk1_ids: Optional[List[int]] = None,
        fk2_ids: Optional[List[int]] = None,
        fk3_ids: Optional[List[int]] = None,
        fk4_ids: Optional[List[int]] = None,
        pk_ids: Optional[List[int]] = None,
        ...
    ):
        some_instances_queryset = SomeModelClass.objects.all()
        if fk1_ids is not None:
            some_instances_queryset =
some_instances_queryset.filter(fk1_id__in=fk1_ids)
        if fk2_ids is not None:
            some_instances_queryset =
some_instances_queryset.filter(fk2_id__in=fk2_ids)
        if fk3_ids is not None:
            some_instances_queryset =
some_instances_queryset.filter(fk3_id__in=fk3_ids)
        if fk4_ids is not None:
            some_instances_queryset =
some_instances_queryset.filter(fk4_id__in=fk4_ids)
        if pk_ids is not None:
            some_instances_queryset =
some_instances_queryset.filter(id__in=pk_ids)
        for some_instance in some_instances_queryset:
            ...
    - after:
    def some_function(
        fk1_ids: Optional[List[int]] = EnhancedQuerySet.IGNORE_FILTER,
        fk2_ids: Optional[List[int]] = EnhancedQuerySet.IGNORE_FILTER,
        fk3_ids: Optional[List[int]] = EnhancedQuerySet.IGNORE_FILTER,
        fk4_ids: Optional[List[int]] = EnhancedQuerySet.IGNORE_FILTER,
        pk_ids: Optional[List[int]] = EnhancedQuerySet.IGNORE_FILTER,
        ...
    ):
        some_instances_queryset = EnhancedQuerySet(SomeModelClass.objects.all())
        some_instances_queryset.filter(
            fk1_id__in=fk1_ids,
            fk2_id__in=fk2_ids,
            fk3_id__in=fk3_ids,
            fk4_id__in=fk4_ids,
            id__in=pk_ids,
        )
        for some_instance in some_instances_queryset:
            ...
    You may alias EnhancedQuerySet for shorter code :
    from ... import EnhancedQuerySet as EQS
        def some_function(
        fk1_ids: Optional[List[int]] = EQS.IGNORE_FILTER,
        fk2_ids: Optional[List[int]] = EQS.IGNORE_FILTER,
        fk3_ids: Optional[List[int]] = EQS.IGNORE_FILTER,
        fk4_ids: Optional[List[int]] = EQS.IGNORE_FILTER,
        pk_ids: Optional[List[int]] = EQS.IGNORE_FILTER,
        ...
    ):
        some_instances_queryset = EQS(SomeModelClass.objects.all())
        some_instances_queryset.filter(
            fk1_id__in=fk1_ids,
            fk2_id__in=fk2_ids,
            fk3_id__in=fk3_ids,
            fk4_id__in=fk4_ids,
            id__in=pk_ids,
        )
        for some_instance in some_instances_queryset:
            ...
    """

    IGNORE_FILTER = object()  # a sentinel for ignoring some filter to
distinguish from None

    def __init__(self, queryset):
        self.queryset = queryset

    def _get_true_kwargs(self, kwargs: dict):
        true_kw_args = {}
        for key, value in kwargs.items():
            if value is EnhancedQuerySet.IGNORE_FILTER:
                continue
            true_kw_args[key] = value
        return true_kw_args

    def filter(self, *args, **kwargs):
        """
        Enhanced filter function with 2 features :
        - ignore some filters given with some default value
        - never forget the affectation after filtering, i.e. avoid this mistake:
            queryset.filter()
            instead of queryset = queryset.filter()
        """
        true_kw_args = self._get_true_kwargs(kwargs)
        self.queryset = self.queryset.filter(*args, **true_kw_args)

    def exclude(self, *args, **kwargs):
        """
        Similar to filter method but with exclude
        """
        true_kw_args = self._get_true_kwargs(kwargs)
        self.queryset = self.queryset.exclude(*args, **true_kw_args)


Best regards,
     Laurent Lyaudet

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAB1LBmuQAVKnA_x4zV6sV%2BrEDeA8NbMA2LZkNOMQfVC9ke8E_g%40mail.gmail.com.

Reply via email to