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