mirror of https://gitlab.crans.org/bde/nk20
Improve REST API with filters
This commit is contained in:
parent
bc97eb1eb4
commit
417cd5da04
|
@ -1,7 +1,8 @@
|
|||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.filters import SearchFilter
|
||||
|
||||
from .serializers import ActivityTypeSerializer, ActivitySerializer, GuestSerializer
|
||||
from ..models import ActivityType, Activity, Guest
|
||||
|
@ -15,6 +16,8 @@ class ActivityTypeViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = ActivityType.objects.all()
|
||||
serializer_class = ActivityTypeSerializer
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_fields = ['name', 'can_invite', ]
|
||||
|
||||
|
||||
class ActivityViewSet(viewsets.ModelViewSet):
|
||||
|
@ -25,6 +28,8 @@ class ActivityViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = Activity.objects.all()
|
||||
serializer_class = ActivitySerializer
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_fields = ['name', 'description', 'activity_type', ]
|
||||
|
||||
|
||||
class GuestViewSet(viewsets.ModelViewSet):
|
||||
|
@ -35,3 +40,5 @@ class GuestViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = Guest.objects.all()
|
||||
serializer_class = GuestSerializer
|
||||
filter_backends = [SearchFilter]
|
||||
search_fields = ['$name', ]
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
from django.conf.urls import url, include
|
||||
from django.contrib.auth.models import User
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework import routers, serializers, viewsets
|
||||
from rest_framework.filters import SearchFilter
|
||||
from activity.api.urls import register_activity_urls
|
||||
from member.api.urls import register_members_urls
|
||||
from note.api.urls import register_note_urls
|
||||
|
@ -33,6 +35,9 @@ class UserViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = User.objects.all()
|
||||
serializer_class = UserSerializer
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter]
|
||||
filterset_fields = ['id', 'username', 'first_name', 'last_name', 'email', 'is_superuser', 'is_staff', 'is_active', ]
|
||||
search_fields = ['$username', '$first_name', '$last_name', ]
|
||||
|
||||
|
||||
# Routers provide an easy way of automatically determining the URL conf.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework import viewsets
|
||||
|
||||
from .serializers import ChangelogSerializer
|
||||
|
@ -15,3 +16,5 @@ class ChangelogViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = Changelog.objects.all()
|
||||
serializer_class = ChangelogSerializer
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_fields = ['model', 'action', "instance_pk", 'user', 'ip',]
|
||||
|
|
|
@ -81,7 +81,7 @@ def save_object(sender, instance, **kwargs):
|
|||
model = instance.__class__
|
||||
fields = '__all__'
|
||||
|
||||
previous_json = JSONRenderer().render(CustomSerializer(previous).data).decode("UTF-8")
|
||||
previous_json = JSONRenderer().render(CustomSerializer(previous).data).decode("UTF-8") if previous else None
|
||||
instance_json = JSONRenderer().render(CustomSerializer(instance).data).decode("UTF-8")
|
||||
|
||||
if previous_json == instance_json:
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
app_name = 'logs'
|
||||
|
||||
# TODO User interface
|
||||
urlpatterns = [
|
||||
]
|
|
@ -2,6 +2,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.filters import SearchFilter
|
||||
|
||||
from .serializers import ProfileSerializer, ClubSerializer, RoleSerializer, MembershipSerializer
|
||||
from ..models import Profile, Club, Role, Membership
|
||||
|
@ -25,6 +26,8 @@ class ClubViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = Club.objects.all()
|
||||
serializer_class = ClubSerializer
|
||||
filter_backends = [SearchFilter]
|
||||
search_fields = ['$name', ]
|
||||
|
||||
|
||||
class RoleViewSet(viewsets.ModelViewSet):
|
||||
|
@ -35,6 +38,8 @@ class RoleViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = Role.objects.all()
|
||||
serializer_class = RoleSerializer
|
||||
filter_backends = [SearchFilter]
|
||||
search_fields = ['$name', ]
|
||||
|
||||
|
||||
class MembershipViewSet(viewsets.ModelViewSet):
|
||||
|
|
|
@ -5,7 +5,8 @@ from rest_framework import serializers
|
|||
from rest_polymorphic.serializers import PolymorphicSerializer
|
||||
|
||||
from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
|
||||
from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory
|
||||
from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory, \
|
||||
TemplateTransaction
|
||||
|
||||
|
||||
class NoteSerializer(serializers.ModelSerializer):
|
||||
|
@ -111,6 +112,17 @@ class TransactionSerializer(serializers.ModelSerializer):
|
|||
fields = '__all__'
|
||||
|
||||
|
||||
class TemplateTransactionSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
REST API Serializer for Transactions.
|
||||
The djangorestframework plugin will analyse the model `TemplateTransaction` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = TemplateTransaction
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class MembershipTransactionSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
REST API Serializer for Membership transactions.
|
||||
|
@ -120,3 +132,11 @@ class MembershipTransactionSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = MembershipTransaction
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class TransactionPolymorphicSerializer(PolymorphicSerializer):
|
||||
model_serializer_mapping = {
|
||||
Transaction: TransactionSerializer,
|
||||
TemplateTransaction: TemplateTransactionSerializer,
|
||||
MembershipTransaction: MembershipTransactionSerializer,
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from .views import NotePolymorphicViewSet, AliasViewSet, \
|
||||
TemplateCategoryViewSet, TransactionViewSet, TransactionTemplateViewSet, MembershipTransactionViewSet
|
||||
TemplateCategoryViewSet, TransactionViewSet, TransactionTemplateViewSet
|
||||
|
||||
|
||||
def register_note_urls(router, path):
|
||||
|
@ -15,4 +15,3 @@ def register_note_urls(router, path):
|
|||
router.register(path + '/transaction/category', TemplateCategoryViewSet)
|
||||
router.register(path + '/transaction/transaction', TransactionViewSet)
|
||||
router.register(path + '/transaction/template', TransactionTemplateViewSet)
|
||||
router.register(path + '/transaction/membership', MembershipTransactionViewSet)
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django.db.models import Q
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.filters import SearchFilter
|
||||
|
||||
from .serializers import NoteSerializer, NotePolymorphicSerializer, NoteClubSerializer, NoteSpecialSerializer, \
|
||||
NoteUserSerializer, AliasSerializer, \
|
||||
TemplateCategorySerializer, TransactionTemplateSerializer, TransactionSerializer, MembershipTransactionSerializer
|
||||
TemplateCategorySerializer, TransactionTemplateSerializer, TransactionPolymorphicSerializer
|
||||
from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
|
||||
from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory
|
||||
from ..models.transactions import TransactionTemplate, Transaction, TemplateCategory
|
||||
|
||||
|
||||
class NoteViewSet(viewsets.ModelViewSet):
|
||||
|
@ -139,6 +141,8 @@ class TemplateCategoryViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = TemplateCategory.objects.all()
|
||||
serializer_class = TemplateCategorySerializer
|
||||
filter_backends = [SearchFilter]
|
||||
search_fields = ['$name', ]
|
||||
|
||||
|
||||
class TransactionTemplateViewSet(viewsets.ModelViewSet):
|
||||
|
@ -149,6 +153,8 @@ class TransactionTemplateViewSet(viewsets.ModelViewSet):
|
|||
"""
|
||||
queryset = TransactionTemplate.objects.all()
|
||||
serializer_class = TransactionTemplateSerializer
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
filterset_fields = ['name', 'amount', 'display', 'category', ]
|
||||
|
||||
|
||||
class TransactionViewSet(viewsets.ModelViewSet):
|
||||
|
@ -158,14 +164,6 @@ class TransactionViewSet(viewsets.ModelViewSet):
|
|||
then render it on /api/note/transaction/transaction/
|
||||
"""
|
||||
queryset = Transaction.objects.all()
|
||||
serializer_class = TransactionSerializer
|
||||
|
||||
|
||||
class MembershipTransactionViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
REST API View set.
|
||||
The djangorestframework plugin will get all `MembershipTransaction` objects, serialize it to JSON with the given serializer,
|
||||
then render it on /api/note/transaction/membership/
|
||||
"""
|
||||
queryset = MembershipTransaction.objects.all()
|
||||
serializer_class = MembershipTransactionSerializer
|
||||
serializer_class = TransactionPolymorphicSerializer
|
||||
filter_backends = [SearchFilter]
|
||||
search_fields = ['$reason', ]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"model": "note.note",
|
||||
"pk": 1,
|
||||
"fields": {
|
||||
"polymorphic_ctype": 37,
|
||||
"polymorphic_ctype": 40,
|
||||
"balance": 0,
|
||||
"is_active": true,
|
||||
"display_image": "",
|
||||
|
@ -14,7 +14,7 @@
|
|||
"model": "note.note",
|
||||
"pk": 2,
|
||||
"fields": {
|
||||
"polymorphic_ctype": 37,
|
||||
"polymorphic_ctype": 40,
|
||||
"balance": 0,
|
||||
"is_active": true,
|
||||
"display_image": "",
|
||||
|
@ -25,7 +25,7 @@
|
|||
"model": "note.note",
|
||||
"pk": 3,
|
||||
"fields": {
|
||||
"polymorphic_ctype": 37,
|
||||
"polymorphic_ctype": 40,
|
||||
"balance": 0,
|
||||
"is_active": true,
|
||||
"display_image": "",
|
||||
|
@ -36,7 +36,7 @@
|
|||
"model": "note.note",
|
||||
"pk": 4,
|
||||
"fields": {
|
||||
"polymorphic_ctype": 37,
|
||||
"polymorphic_ctype": 40,
|
||||
"balance": 0,
|
||||
"is_active": true,
|
||||
"display_image": "",
|
||||
|
@ -47,7 +47,7 @@
|
|||
"model": "note.note",
|
||||
"pk": 5,
|
||||
"fields": {
|
||||
"polymorphic_ctype": 36,
|
||||
"polymorphic_ctype": 39,
|
||||
"balance": 0,
|
||||
"is_active": true,
|
||||
"display_image": "",
|
||||
|
@ -58,7 +58,7 @@
|
|||
"model": "note.note",
|
||||
"pk": 6,
|
||||
"fields": {
|
||||
"polymorphic_ctype": 36,
|
||||
"polymorphic_ctype": 39,
|
||||
"balance": 0,
|
||||
"is_active": true,
|
||||
"display_image": "",
|
||||
|
|
|
@ -137,12 +137,14 @@ REST_FRAMEWORK = {
|
|||
# or allow read-only access for unauthenticated users.
|
||||
'DEFAULT_PERMISSION_CLASSES': [
|
||||
# TODO Maybe replace it with our custom permissions system
|
||||
'rest_framework.permissions.DjangoModelPermissions'
|
||||
'rest_framework.permissions.DjangoModelPermissions',
|
||||
],
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
'rest_framework.authentication.TokenAuthentication',
|
||||
]
|
||||
],
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
||||
'PAGE_SIZE': 20,
|
||||
}
|
||||
|
||||
# Internationalization
|
||||
|
|
|
@ -20,8 +20,7 @@ urlpatterns = [
|
|||
path('accounts/', include('django.contrib.auth.urls')),
|
||||
path('admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
path('admin/', admin.site.urls),
|
||||
path('logs/', include('logs.urls')),
|
||||
path('api/', include('api.urls')),
|
||||
path('api/', include('api.urls')),
|
||||
]
|
||||
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{% load crispy_forms_tags %}
|
||||
{% load i18n %}
|
||||
|
||||
<h2>{% trans "Field filters" %}</h2>
|
||||
{% crispy filter.form %}
|
|
@ -0,0 +1,6 @@
|
|||
{% load i18n %}
|
||||
<h2>{% trans "Field filters" %}</h2>
|
||||
<form class="form" action="" method="get">
|
||||
{{ filter.form.as_p }}
|
||||
<button type="submit" class="btn btn-primary">{% trans "Submit" %}</button>
|
||||
</form>
|
|
@ -0,0 +1 @@
|
|||
{% for widget in widget.subwidgets %}{% include widget.template_name %}{% if forloop.first %}-{% endif %}{% endfor %}
|
Loading…
Reference in New Issue