Home > Blockchain >  Simplify writing if/else collection of Django queries
Simplify writing if/else collection of Django queries

Time:12-26

I have code in a Django views.py that looks like:

if query_type == 'list':

    if column == 'person':
        person_qs = Person.objects.filter(name__in = query_items_set)

    elif column == 'grandparent':
        person_qs = Person.objects.filter(grandparent__name__in = query_items_set)

    elif column == 'child':
        person_qs = Person.objects.filter(child__name__in = query_items_set)

elif query_type == 'regex':

    if column == 'person':
        person_qs = Person.objects.filter(name__regex = regex_query)

    elif column == 'grandparent':
        person_qs = Person.objects.filter(grandparent__name__regex = regex_query)

    elif column == 'child':
        person_qs = Person.objects.filter(child__name__regex = regex_query)

When it comes to writing views, is there a more accepted/concise way of avoiding repitition, while still maintaining readability and extensibility? Or do views.py files tend to look like this? Or are dispatch tables more common?

CodePudding user response:

For cases like this DRF (Django REST Framework) is a common and very useful solution. Here are the docs about filtering.

An example.

View:

from myapp.models import Person
from myapp.serializers import PersonSerializer
from rest_framework import generics

class PersonList(generics.ListAPIView):
    serializer_class = PersonSerializer
    filter_backends = [
        SearchFilter
    ]
    search_fields = [
        'name', 'grandparent__name', 'child__name',  # For substring search
        '$name', '$grandparent__name', '$child__name'  # For regex search
    ]

And you will also need a Serializer:

class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = '__all__'

That's all.

CodePudding user response:

Thanks to everyone who suggested django-filter.

> pip install django-filter

settings.py

INSTALLED_APPS = [
    ...
    'django_filters',
]

views.py

class PersonFilter(django_filters.FilterSet):
    class Meta:
        model = Person
        fields = {'name': ['exact', 'regex'], 
                  'child__name': ['exact', 'regex'], 
                  'grandparent__name': ['exact', 'regex']}

        ...

        person_qs = PersonFilter(request.GET, queryset = Person.objects.all().qs
  • Related