Skip to content

Commit

Permalink
Use django-filters to improve API filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
kfdm committed Mar 29, 2019
1 parent 5e13739 commit 5893507
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 43 deletions.
8 changes: 8 additions & 0 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions docker/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ certifi==2018.10.15
chardet==3.0.4
defusedxml==0.5.0 ; python_version >= '3.0'
dj-database-url==0.5.0
django-filter==2.1.0
django==2.1.2
djangorestframework==3.9.0
envdir==1.0.1
gunicorn==19.9.0
idna==2.7
Expand All @@ -20,12 +22,12 @@ python3-openid==3.1.0 ; python_version >= '3.0'
pytz==2018.7
pyyaml==3.13
raven==6.9.0
redis==2.10.6
redis==3.0.1
requests-oauthlib==1.0.0
requests==2.20.0
requests==2.20.1
six==1.11.0
social-auth-app-django==3.1.0
social-auth-core==2.0.0
urllib3==1.24.1
vine==1.1.4
whitenoise==4.1
whitenoise==4.1.2
28 changes: 28 additions & 0 deletions promgen/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import django_filters


class ShardFilter(django_filters.rest_framework.FilterSet):
name = django_filters.CharFilter(field_name="name", lookup_expr="contains")


class ServiceFilter(django_filters.rest_framework.FilterSet):
name = django_filters.CharFilter(field_name="name", lookup_expr="contains")
shard = django_filters.CharFilter(field_name="shard__name", lookup_expr="contains")


class ProjectFilter(django_filters.rest_framework.FilterSet):
name = django_filters.CharFilter(field_name="name", lookup_expr="contains")
service = django_filters.CharFilter(
field_name="service__name", lookup_expr="contains"
)
shard = django_filters.CharFilter(
field_name="service__shard__name", lookup_expr="contains"
)


class RuleFilter(django_filters.rest_framework.FilterSet):
name = django_filters.CharFilter(field_name="name", lookup_expr="contains")
parent = django_filters.CharFilter(
field_name="parent__name", lookup_expr="contains"
)
enabled = django_filters.BooleanFilter(field_name="enabled")
5 changes: 4 additions & 1 deletion promgen/rest.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from django.conf import settings
from django.http import HttpResponse
from promgen import models, prometheus, serializers
from promgen import filters, models, prometheus, serializers
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response


class ShardViewSet(viewsets.ModelViewSet):
queryset = models.Shard.objects.all()
filterset_class = filters.ShardFilter
serializer_class = serializers.ShardSerializer
lookup_field = 'name'

Expand Down Expand Up @@ -35,6 +36,7 @@ def format(self, rules=None, name='promgen'):

class ServiceViewSet(SharedViewSet, viewsets.ModelViewSet):
queryset = models.Service.objects.prefetch_related('shard')
filterset_class = filters.ServiceFilter
serializer_class = serializers.ServiceSerializer
lookup_value_regex = '[^/]+'
lookup_field = 'name'
Expand Down Expand Up @@ -71,6 +73,7 @@ class ProjectViewSet(SharedViewSet, viewsets.ModelViewSet):
queryset = models.Project.objects.prefetch_related(
'service', 'service__shard', 'farm'
)
filterset_class = filters.ProjectFilter
serializer_class = serializers.ProjectSerializer
lookup_value_regex = '[^/]+'
lookup_field = 'name'
Expand Down
52 changes: 16 additions & 36 deletions promgen/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
from rest_framework import serializers


class ShardSerializer(serializers.ModelSerializer):
_html = serializers.SerializerMethodField()
_services = serializers.SerializerMethodField()
class WebLinkField(serializers.Field):
def get_attribute(self, instance):
return instance

def to_representation(self, obj):
return shortcuts.resolve_domain(obj.get_absolute_url())

def get__html(self, obj):
return shortcuts.resolve_domain('shard-detail', obj.id)

def get__services(self, obj):
return shortcuts.resolve_domain('api:shard-services', obj.name)
class ShardSerializer(serializers.ModelSerializer):
html = WebLinkField()

class Meta:
model = models.Shard
Expand All @@ -19,20 +20,9 @@ class Meta:


class ServiceSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')

_shard = serializers.SerializerMethodField()
_projects = serializers.SerializerMethodField()
_html = serializers.SerializerMethodField()

def get__html(self, obj):
return shortcuts.resolve_domain('service-detail', obj.id)

def get__shard(self, obj):
return shortcuts.resolve_domain('api:shard-detail', obj.shard.name)

def get__projects(self, obj):
return shortcuts.resolve_domain('api:service-projects', obj.name)
owner = serializers.ReadOnlyField(source="owner.username")
shard = serializers.ReadOnlyField(source="shard.name")
html = WebLinkField()

class Meta:
model = models.Service
Expand All @@ -41,25 +31,15 @@ class Meta:


class ProjectSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')

_html = serializers.SerializerMethodField()
_service = serializers.SerializerMethodField()
_shard = serializers.SerializerMethodField()

def get__html(self, obj):
return shortcuts.resolve_domain('project-detail', obj.id)

def get__service(self, obj):
return shortcuts.resolve_domain('api:service-detail', obj.service.name)

def get__shard(self, obj):
return shortcuts.resolve_domain('api:shard-detail', obj.service.shard.name)
owner = serializers.ReadOnlyField(source="owner.username")
service = serializers.ReadOnlyField(source="service.name")
shard = serializers.ReadOnlyField(source="service.shard.name")
html = WebLinkField()

class Meta:
model = models.Project
exclude = ('id', 'service', 'farm')
lookup_field = 'name'
exclude = ("id", "farm")


class SenderSerializer(serializers.ModelSerializer):
Expand Down
4 changes: 4 additions & 0 deletions promgen/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
'promgen',
'rest_framework',
'rest_framework.authtoken',
'django_filters',
]

# We explicitly include debug_toolbar and whitenoise here, but selectively
Expand Down Expand Up @@ -206,6 +207,9 @@
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
),
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
)
}

Expand Down
4 changes: 2 additions & 2 deletions promgen/templates/rest_framework/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
<link rel="stylesheet" href="{% static "/css/bootstrap.min.css" %}">
<link rel="stylesheet" href="{% static "/css/bootstrap-theme.min.css" %}">
<link rel="stylesheet" href="{% static "/css/bootstrap-switch.min.css" %}">
<!-- <link rel="stylesheet" href="{% static "/css/promgen.css" %}"> -->
<link rel="stylesheet" href="{% static "/css/promgen.css" %}">
<link rel="icon" href="{% static "/images/promgen_logo_color.png" %}">
{% endblock %}

{% block script %}
Expand All @@ -32,4 +33,3 @@
});
</script>
{% endblock %}

3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@
'atomicwrites',
'celery[redis]==4.1.1',
'dj-database-url',
'djangorestframework==3.9.0',
'django-filter',
'Django==2.1.2',
'djangorestframework==3.9.0',
'envdir',
'prometheus-client',
'python-dateutil',
Expand Down

0 comments on commit 5893507

Please sign in to comment.