From 94640a70fac63c16bf900c42c1d4e339273c3e27 Mon Sep 17 00:00:00 2001 From: MOIS3Y Date: Fri, 11 Aug 2023 22:12:51 +0900 Subject: [PATCH] Add: simple filters to modelviewsets --- logs_collector/collector/filters.py | 39 +++++++++++++++++++++++ logs_collector/collector/urls.py | 2 +- logs_collector/collector/utils.py | 26 +++++++++++++-- logs_collector/collector/views.py | 14 ++++++-- logs_collector/logs_collector/settings.py | 2 ++ poetry.lock | 16 +++++++++- pyproject.toml | 1 + 7 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 logs_collector/collector/filters.py diff --git a/logs_collector/collector/filters.py b/logs_collector/collector/filters.py new file mode 100644 index 0000000..ab1b9c6 --- /dev/null +++ b/logs_collector/collector/filters.py @@ -0,0 +1,39 @@ +from django_filters.rest_framework import ( + CharFilter, + FilterSet, + NumberFilter, +) +from django_filters import widgets + +from .models import Archive, Ticket +from .utils import DateTimeFilterMixin + + +class ArchiveFilter(DateTimeFilterMixin, FilterSet): + + class Meta: + model = Archive + fields = { + 'id': ['exact', 'in', 'lte', 'gte'], + 'ticket': ['exact', 'in', 'lte', 'gte'], + 'time_create': ['exact', 'lte', 'gte'] + } + + +class TicketFilter(DateTimeFilterMixin, FilterSet): + number = NumberFilter( + field_name='number', + widget=widgets.CSVWidget(), + ) + user = CharFilter( + field_name='user__username' + ) + + class Meta: + model = Ticket + fields = { + 'id': ['exact', 'in', 'lte', 'gte'], + 'number': ['exact', 'contains', 'in', 'lte', 'gte'], + 'resolved': ['exact'], + 'user': ['exact'] + } diff --git a/logs_collector/collector/urls.py b/logs_collector/collector/urls.py index cdf05b3..485690c 100644 --- a/logs_collector/collector/urls.py +++ b/logs_collector/collector/urls.py @@ -77,6 +77,6 @@ urlpatterns = [ # █▀█ █▀▀ █ # -- -- -- - # CREATE: + # CRUD: path('api/v1/', include(router.urls)) ] diff --git a/logs_collector/collector/utils.py b/logs_collector/collector/utils.py index 0d752dc..6d64a44 100644 --- a/logs_collector/collector/utils.py +++ b/logs_collector/collector/utils.py @@ -1,9 +1,12 @@ import os +from django_filters import NumberFilter def logs_dir_path(instance, filename): - # file will be uploaded to - # MEDIA_ROOT_FOR_SENSITIVE_FILES// + """ + file will be uploaded to + MEDIA_ROOT_FOR_SENSITIVE_FILES// + """ return f'{instance.ticket.number}/{filename}' @@ -37,3 +40,22 @@ class PageTitleViewMixin: context = super().get_context_data(**kwargs) context['title'] = self.get_title() return context + + +class DateTimeFilterMixin: + year__gte = NumberFilter( + field_name='time_create', + lookup_expr='year__gte' + ) + year__lte = NumberFilter( + field_name='time_create', + lookup_expr='year__lte' + ) + month__gte = NumberFilter( + field_name='time_create', + lookup_expr='month__gte' + ) + month__lte = NumberFilter( + field_name='time_create', + lookup_expr='month__lte' + ) diff --git a/logs_collector/collector/views.py b/logs_collector/collector/views.py index 3c66ef0..2f8523b 100644 --- a/logs_collector/collector/views.py +++ b/logs_collector/collector/views.py @@ -12,12 +12,14 @@ from rest_framework import status from rest_framework.parsers import FormParser, MultiPartParser from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response - -# from rest_framework import mixins from rest_framework import viewsets +from rest_framework import filters + +from django_filters.rest_framework import DjangoFilterBackend from .models import Archive, Ticket, Platform from .forms import TicketForm +from .filters import ArchiveFilter, TicketFilter from .utils import PageTitleViewMixin, is_ajax from .permissions import IsGuestUpload @@ -187,6 +189,8 @@ class ArchiveViewSet(viewsets.ModelViewSet): serializer_class = ArchiveSerializer parser_classes = (MultiPartParser, FormParser) permission_classes = (IsGuestUpload, ) + filter_backends = [DjangoFilterBackend] + filterset_class = ArchiveFilter def create(self, request, *args, **kwargs): # ! upload-token protection: @@ -244,3 +248,9 @@ class TicketViewSet(viewsets.ModelViewSet): lookup_field = 'number' serializer_class = TicketSerializer permission_classes = (IsAuthenticated, ) + filter_backends = [DjangoFilterBackend, filters.SearchFilter] + filterset_class = TicketFilter + search_fields = ['number'] + + def perform_create(self, serializer): + serializer.save(user=self.request.user) diff --git a/logs_collector/logs_collector/settings.py b/logs_collector/logs_collector/settings.py index 52e1cf2..f57e071 100644 --- a/logs_collector/logs_collector/settings.py +++ b/logs_collector/logs_collector/settings.py @@ -35,6 +35,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'collector.apps.CollectorConfig', # main app 'rest_framework', + 'django_filters', "crispy_forms", "crispy_bootstrap5", 'django_cleanup.apps.CleanupConfig', # required bottom @@ -147,6 +148,7 @@ REST_FRAMEWORK = { 'rest_framework.renderers.BrowsableAPIRenderer', 'rest_framework.parsers.MultiPartParser' ], + 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend', ], # noqa:E501 # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', # noqa:E501 # 'PAGE_SIZE': 3, } diff --git a/poetry.lock b/poetry.lock index b88c7dc..2648e18 100644 --- a/poetry.lock +++ b/poetry.lock @@ -96,6 +96,20 @@ develop = ["coverage[toml] (>=5.0a4)", "furo (>=2021.8.17b43,<2021.9.dev0)", "py docs = ["furo (>=2021.8.17b43,<2021.9.dev0)", "sphinx (>=3.5.0)", "sphinx-notfound-page"] testing = ["coverage[toml] (>=5.0a4)", "pytest (>=4.6.11)"] +[[package]] +name = "django-filter" +version = "23.2" +description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." +optional = false +python-versions = ">=3.7" +files = [ + {file = "django-filter-23.2.tar.gz", hash = "sha256:2fe15f78108475eda525692813205fa6f9e8c1caf1ae65daa5862d403c6dbf00"}, + {file = "django_filter-23.2-py3-none-any.whl", hash = "sha256:d12d8e0fc6d3eb26641e553e5d53b191eb8cec611427d4bdce0becb1f7c172b5"}, +] + +[package.dependencies] +Django = ">=3.2" + [[package]] name = "djangorestframework" version = "3.14.0" @@ -268,4 +282,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "1fc8f57d5dd1b53de4879607d1c7e7c8d9acafd9cbafe4ff64763766d69a4d51" +content-hash = "b42d414f4fc2d5e6e441406720910dce9e6f2c57dab1fb935de691a32715c287" diff --git a/pyproject.toml b/pyproject.toml index 7f2ca24..edb81cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ django-cleanup = "^8.0.0" django-crispy-forms = "^2.0" crispy-bootstrap5 = "^0.7" markdown = "^3.4.4" +django-filter = "^23.2" [tool.poetry.group.dev.dependencies] flake8 = "^6.0.0"