Login

EnhancedQuerySet

Author:
LLyaudet
Posted:
April 5, 2022
Language:
Python
Version:
3.2
Score:
0 (after 0 ratings)

A proxy for Django queryset attempting to avoid boilerplate code with ifs and avoid bugs when affectation of result is not done.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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.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.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)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 4 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

Please login first before commenting.