Some serialization BS
This commit is contained in:
+1
-3
@@ -127,9 +127,7 @@ MIDDLEWARE = [
|
|||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
'auditlog.middleware.AuditlogMiddleware'
|
'auditlog.middleware.AuditlogMiddleware'
|
||||||
]
|
]
|
||||||
MIDDLEWARE_CLASSES = [
|
|
||||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
|
||||||
]
|
|
||||||
CORS_ORIGIN_ALLOW_ALL = True
|
CORS_ORIGIN_ALLOW_ALL = True
|
||||||
|
|
||||||
ROOT_URLCONF = 'sikweb.urls'
|
ROOT_URLCONF = 'sikweb.urls'
|
||||||
|
|||||||
@@ -108,6 +108,11 @@ class SignupForm(models.Model):
|
|||||||
def signups(self):
|
def signups(self):
|
||||||
return Signup.objects.filter(signupForm=self).order_by('pk')
|
return Signup.objects.filter(signupForm=self).order_by('pk')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def isOpen(self):
|
||||||
|
now = timezone.now()
|
||||||
|
return self.start_time <= now and now < self.end_time
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('Signup form')
|
verbose_name = _('Signup form')
|
||||||
verbose_name_plural = _('Signup forms')
|
verbose_name_plural = _('Signup forms')
|
||||||
|
|||||||
+19
-17
@@ -7,7 +7,6 @@ class SignupSerializer(serializers.ModelSerializer):
|
|||||||
source="signupForm",
|
source="signupForm",
|
||||||
queryset=SignupForm.objects.all()
|
queryset=SignupForm.objects.all()
|
||||||
)
|
)
|
||||||
answer = serializers.JSONField()
|
|
||||||
list_name = serializers.CharField(read_only=True)
|
list_name = serializers.CharField(read_only=True)
|
||||||
|
|
||||||
def add_extra_fields(self, validated_data):
|
def add_extra_fields(self, validated_data):
|
||||||
@@ -44,8 +43,7 @@ class SignupSerializer(serializers.ModelSerializer):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SignupFormSerializer(serializers.HyperlinkedModelSerializer):
|
class SignupFormSerializer(serializers.ModelSerializer):
|
||||||
questions = serializers.JSONField()
|
|
||||||
signups = serializers.SlugRelatedField(
|
signups = serializers.SlugRelatedField(
|
||||||
slug_field="list_name",
|
slug_field="list_name",
|
||||||
many=True,
|
many=True,
|
||||||
@@ -55,36 +53,37 @@ class SignupFormSerializer(serializers.HyperlinkedModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SignupForm
|
model = SignupForm
|
||||||
fields = ('id', 'title', 'visible', 'start_time', 'end_time', 'questions', 'schema', 'signups', 'quota')
|
fields = ('id', 'title', 'visible', 'isOpen', 'start_time', 'end_time', 'questions', 'schema', 'signups', 'quota')
|
||||||
|
|
||||||
|
|
||||||
class EventSerializer(serializers.ModelSerializer):
|
class EventSerializer(serializers.ModelSerializer):
|
||||||
signupForm = SignupFormSerializer(
|
signupForm = SignupFormSerializer(
|
||||||
|
source='filtered_signup_forms',
|
||||||
many=True,
|
many=True,
|
||||||
read_only=True,
|
read_only=True,
|
||||||
required=False,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
signup_id = serializers.PrimaryKeyRelatedField(
|
signup_id = serializers.PrimaryKeyRelatedField(
|
||||||
many=True,
|
|
||||||
source="signupForm",
|
|
||||||
queryset=SignupForm.objects.all(),
|
queryset=SignupForm.objects.all(),
|
||||||
required=False
|
many=True,
|
||||||
|
write_only=True,
|
||||||
)
|
)
|
||||||
tag_id = serializers.PrimaryKeyRelatedField(
|
tag_id = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=Tag.objects.all(),
|
||||||
many=True,
|
many=True,
|
||||||
source="tags",
|
write_only=True,
|
||||||
queryset=Tag.objects.all()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Event
|
model = Event
|
||||||
fields = ('id', 'tag_id', 'tags', 'visible', 'image', 'title_fi', 'title_en', 'description_fi', 'description_en',
|
fields = ('id', 'tag_id', 'tags', 'visible', 'image', 'title_fi', 'title_en', 'description_fi', 'description_en',
|
||||||
'content_fi', 'content_en', 'start_time', 'end_time', 'location', 'signup_id', 'signupForm')
|
'content_fi', 'content_en', 'start_time', 'end_time', 'location', 'signup_id', 'signupForm')
|
||||||
|
read_only_fields = ['tags', 'signupForm']
|
||||||
depth = 1
|
depth = 1
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
signupForms = validated_data.pop('signupForm', [])
|
signupForms = validated_data.pop('signup_id', [])
|
||||||
tags = validated_data.pop('tags')
|
tags = validated_data.pop('tag_id')
|
||||||
event = Event.objects.create(**validated_data)
|
event = Event.objects.create(**validated_data)
|
||||||
for form in signupForms:
|
for form in signupForms:
|
||||||
event.signupForm.add(form)
|
event.signupForm.add(form)
|
||||||
@@ -94,12 +93,15 @@ class EventSerializer(serializers.ModelSerializer):
|
|||||||
return event
|
return event
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
signupForms = validated_data.pop('signupForm', [])
|
signupForms = validated_data.pop('signup_id', [])
|
||||||
instance = super(EventSerializer, self).update(instance, validated_data)
|
tags = validated_data.pop('tag_id')
|
||||||
instance.signupForm.clear()
|
instance.signupForm.clear()
|
||||||
for form_data in signupForms:
|
instance.tags.clear()
|
||||||
# form_qs = SignupForms.objects.filter(id=form['id'])
|
for form in signupForms:
|
||||||
instance.signupForm.add(form_data)
|
instance.signupForm.add(form)
|
||||||
|
for tag in tags:
|
||||||
|
instance.tags.add(tag)
|
||||||
|
instance = super(EventSerializer, self).update(instance, validated_data)
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User, AnonymousUser
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.test import APITestCase, APIRequestFactory
|
from rest_framework.test import APITestCase, APIRequestFactory
|
||||||
@@ -57,11 +57,13 @@ class EventTestCase(APITestCase):
|
|||||||
# Response should not have old events and invisible
|
# Response should not have old events and invisible
|
||||||
self.assertEqual(len(response.data["results"]), 2)
|
self.assertEqual(len(response.data["results"]), 2)
|
||||||
# Check that serialized data is equal to received response
|
# Check that serialized data is equal to received response
|
||||||
|
req = APIRequestFactory().get(r"http://testserver/api/events/")
|
||||||
|
req.user = AnonymousUser()
|
||||||
expected_events = EventSerializer(
|
expected_events = EventSerializer(
|
||||||
Event.objects.filter(title_fi__in=("Testitapahtuma1", "Testitapahtuma4")).order_by("start_time"),
|
Event.objects.filter(title_fi__in=("Testitapahtuma1", "Testitapahtuma4")).order_by("start_time"),
|
||||||
many=True,
|
many=True,
|
||||||
context={
|
context={
|
||||||
"request": APIRequestFactory().get(r"http://testserver/api/events/")
|
"request": req
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.assertEqual(response.data["results"], expected_events.data)
|
self.assertEqual(response.data["results"], expected_events.data)
|
||||||
@@ -71,11 +73,13 @@ class EventTestCase(APITestCase):
|
|||||||
self.assertTrue(response.status_code, status.HTTP_200_OK)
|
self.assertTrue(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertEqual(len(response.data["results"]), 3)
|
self.assertEqual(len(response.data["results"]), 3)
|
||||||
|
|
||||||
|
req = APIRequestFactory().get(r"http://testserver/api/events/")
|
||||||
|
req.user = AnonymousUser()
|
||||||
expected_events = EventSerializer(
|
expected_events = EventSerializer(
|
||||||
Event.objects.filter(title_fi__in=("Testitapahtuma1", "Testitapahtuma3", "Testitapahtuma4")).order_by("start_time"),
|
Event.objects.filter(title_fi__in=("Testitapahtuma1", "Testitapahtuma3", "Testitapahtuma4")).order_by("start_time"),
|
||||||
many=True,
|
many=True,
|
||||||
context={
|
context={
|
||||||
"request": APIRequestFactory().get(r"http://testserver/api/events/")
|
"request": req
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.assertEqual(response.data["results"], expected_events.data)
|
self.assertEqual(response.data["results"], expected_events.data)
|
||||||
@@ -84,10 +88,12 @@ class EventTestCase(APITestCase):
|
|||||||
response = self.client.get(f"{URL}{self.testEventId}/", format="json")
|
response = self.client.get(f"{URL}{self.testEventId}/", format="json")
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
|
||||||
|
req = APIRequestFactory().get(r"http://testserver/api/events/")
|
||||||
|
req.user = AnonymousUser()
|
||||||
serializer = EventSerializer(
|
serializer = EventSerializer(
|
||||||
Event.objects.get(title_fi="Testitapahtuma1"),
|
Event.objects.get(title_fi="Testitapahtuma1"),
|
||||||
context={
|
context={
|
||||||
"request": APIRequestFactory().get(r"http://testserver/api/events/")
|
"request": req
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.assertEqual(response.data, serializer.data)
|
self.assertEqual(response.data, serializer.data)
|
||||||
|
|||||||
@@ -49,6 +49,13 @@ class SignupTestCase(APITestCase):
|
|||||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||||
self.assertEqual(Signup.objects.count(), 3)
|
self.assertEqual(Signup.objects.count(), 3)
|
||||||
|
|
||||||
|
# Can signup to a hidden form
|
||||||
|
def test_create_signup_hidden(self):
|
||||||
|
new = createSignupRequest("asd", self.hiddenForm.id, ALL_QUESTION_TYPES_ANSWER)
|
||||||
|
response = self.client.post(URL, new, format="json")
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||||
|
self.assertEqual(Signup.objects.count(), 3)
|
||||||
|
|
||||||
@skip("NotImplemented")
|
@skip("NotImplemented")
|
||||||
def test_get_hidden_forms_admin(self):
|
def test_get_hidden_forms_admin(self):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from django.utils import timezone
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from unittest import skip
|
from unittest import skip
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
@@ -15,6 +16,10 @@ class SignupErrorTestCase(APITestCase):
|
|||||||
self.signupFormRadio = createSignupForm(name="Form3", questions=[ALL_QUESTION_TYPES[1]], schema=RADIO_SCHEMA)
|
self.signupFormRadio = createSignupForm(name="Form3", questions=[ALL_QUESTION_TYPES[1]], schema=RADIO_SCHEMA)
|
||||||
self.signupFormCheck = createSignupForm(name="Form4", questions=[ALL_QUESTION_TYPES[2]], schema=CBOX_SCHEMA)
|
self.signupFormCheck = createSignupForm(name="Form4", questions=[ALL_QUESTION_TYPES[2]], schema=CBOX_SCHEMA)
|
||||||
self.hiddenForm = createSignupForm(visible=False)
|
self.hiddenForm = createSignupForm(visible=False)
|
||||||
|
day_from_now = timezone.now() + timezone.timedelta(days=1)
|
||||||
|
day_before_now = timezone.now() + timezone.timedelta(days=-1)
|
||||||
|
self.signupFormNotStarted = createSignupForm(start_time=day_from_now, end_time=day_from_now)
|
||||||
|
self.signupFormEnded = createSignupForm(start_time=day_before_now, end_time=timezone.now())
|
||||||
|
|
||||||
self.signup1 = createSignupObject("1", self.signupForm, ALL_QUESTION_TYPES)
|
self.signup1 = createSignupObject("1", self.signupForm, ALL_QUESTION_TYPES)
|
||||||
self.signup2 = createSignupObject("2", self.signupForm, ALL_QUESTION_TYPES)
|
self.signup2 = createSignupObject("2", self.signupForm, ALL_QUESTION_TYPES)
|
||||||
@@ -37,8 +42,14 @@ class SignupErrorTestCase(APITestCase):
|
|||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.assertEqual(Signup.objects.count(), 2)
|
self.assertEqual(Signup.objects.count(), 2)
|
||||||
|
|
||||||
def test_create_signup_hidden(self):
|
def test_create_signup_not_started(self):
|
||||||
new = createSignupRequest("asd", self.hiddenForm.id, ALL_QUESTION_TYPES_ANSWER)
|
new = createSignupRequest("asd", self.signupFormNotStarted.id, ALL_QUESTION_TYPES_ANSWER)
|
||||||
|
response = self.client.post(URL, new, format="json")
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
|
self.assertEqual(Signup.objects.count(), 2)
|
||||||
|
|
||||||
|
def test_create_signup_ended(self):
|
||||||
|
new = createSignupRequest("asd", self.signupFormEnded.id, ALL_QUESTION_TYPES_ANSWER)
|
||||||
response = self.client.post(URL, new, format="json")
|
response = self.client.post(URL, new, format="json")
|
||||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||||
self.assertEqual(Signup.objects.count(), 2)
|
self.assertEqual(Signup.objects.count(), 2)
|
||||||
|
|||||||
+25
-13
@@ -9,8 +9,10 @@ from django.http import HttpResponse, JsonResponse
|
|||||||
from django.shortcuts import render, get_object_or_404
|
from django.shortcuts import render, get_object_or_404
|
||||||
from django.views.decorators.http import require_http_methods
|
from django.views.decorators.http import require_http_methods
|
||||||
from django_filters import rest_framework as filters
|
from django_filters import rest_framework as filters
|
||||||
|
from django.db.models import Prefetch
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from rest_framework import routers, viewsets
|
from rest_framework import routers
|
||||||
|
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
||||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly, BasePermission, AllowAny
|
from rest_framework.permissions import IsAuthenticatedOrReadOnly, BasePermission, AllowAny
|
||||||
@@ -37,7 +39,7 @@ class RootView(routers.APIRootView):
|
|||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
|
|
||||||
class EventViewSet(viewsets.ModelViewSet):
|
class EventViewSet(ModelViewSet):
|
||||||
queryset = Event.objects.all()
|
queryset = Event.objects.all()
|
||||||
ordering = ["start_time"]
|
ordering = ["start_time"]
|
||||||
serializer_class = EventSerializer
|
serializer_class = EventSerializer
|
||||||
@@ -47,13 +49,23 @@ class EventViewSet(viewsets.ModelViewSet):
|
|||||||
# search_fields = '__all__'
|
# search_fields = '__all__'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if self.request.user.is_authenticated:
|
|
||||||
|
if self.request.method == 'POST' or self.request.method == 'PUT':
|
||||||
return Event.objects.all()
|
return Event.objects.all()
|
||||||
|
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
return Event.objects.all().prefetch_related(
|
||||||
|
Prefetch('signupForm', queryset=SignupForm.objects.all(), to_attr='filtered_signup_forms')
|
||||||
|
)
|
||||||
|
|
||||||
since = self.request.query_params.get('since', None)
|
since = self.request.query_params.get('since', None)
|
||||||
if since:
|
if since:
|
||||||
return Event.objects.filter(visible=True, end_time__gt=since).order_by('start_time')
|
return Event.objects.filter(visible=True, end_time__gt=since).order_by('start_time').prefetch_related(
|
||||||
return Event.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time')
|
Prefetch('signupForm', queryset=SignupForm.objects.filter(visible=True), to_attr='filtered_signup_forms')
|
||||||
|
)
|
||||||
|
return Event.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time').prefetch_related(
|
||||||
|
Prefetch('signupForm', queryset=SignupForm.objects.filter(visible=True), to_attr='filtered_signup_forms')
|
||||||
|
)
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
raw_image = request.data.get("image", None)
|
raw_image = request.data.get("image", None)
|
||||||
@@ -74,7 +86,7 @@ class EventViewSet(viewsets.ModelViewSet):
|
|||||||
return super().update(request, *args, **kwargs)
|
return super().update(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class SignupFormViewSet(viewsets.ModelViewSet):
|
class SignupFormViewSet(ModelViewSet):
|
||||||
queryset = SignupForm.objects.all()
|
queryset = SignupForm.objects.all()
|
||||||
serializer_class = SignupFormSerializer
|
serializer_class = SignupFormSerializer
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
@@ -95,7 +107,7 @@ class SignupFormViewSet(viewsets.ModelViewSet):
|
|||||||
return SignupForm.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time')
|
return SignupForm.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time')
|
||||||
|
|
||||||
|
|
||||||
class SignupViewSet(viewsets.ModelViewSet):
|
class SignupViewSet(ModelViewSet):
|
||||||
queryset = Signup.objects.all()
|
queryset = Signup.objects.all()
|
||||||
serializer_class = SignupSerializer
|
serializer_class = SignupSerializer
|
||||||
permission_classes = [SignupPermission]
|
permission_classes = [SignupPermission]
|
||||||
@@ -116,7 +128,7 @@ class SignupViewSet(viewsets.ModelViewSet):
|
|||||||
try:
|
try:
|
||||||
answer = request.data["answer"]
|
answer = request.data["answer"]
|
||||||
form = SignupForm.objects.get(id=id)
|
form = SignupForm.objects.get(id=id)
|
||||||
if (form.visible):
|
if (form.isOpen):
|
||||||
# Throws ValidationError if not valid
|
# Throws ValidationError if not valid
|
||||||
validate(instance=answer, schema=form.schema)
|
validate(instance=answer, schema=form.schema)
|
||||||
return super().create(request, *args, **kwargs)
|
return super().create(request, *args, **kwargs)
|
||||||
@@ -147,13 +159,13 @@ class SignupViewSet(viewsets.ModelViewSet):
|
|||||||
return JsonResponse(status=404, data={"error": f"SignupForm {id} not found"})
|
return JsonResponse(status=404, data={"error": f"SignupForm {id} not found"})
|
||||||
|
|
||||||
|
|
||||||
class SavedQuestionsViewSet(viewsets.ModelViewSet):
|
class SavedQuestionsViewSet(ModelViewSet):
|
||||||
queryset = TemplateQuestion.objects.all()
|
queryset = TemplateQuestion.objects.all()
|
||||||
serializer_class = SavedQuestionsSerializer
|
serializer_class = SavedQuestionsSerializer
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
|
|
||||||
class FeedViewSet(viewsets.ModelViewSet):
|
class FeedViewSet(ModelViewSet):
|
||||||
queryset = Feed.objects.all()
|
queryset = Feed.objects.all()
|
||||||
serializer_class = FeedSerializer
|
serializer_class = FeedSerializer
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
@@ -178,7 +190,7 @@ class FeedViewSet(viewsets.ModelViewSet):
|
|||||||
return Feed.objects.filter(id__in=result_ids)
|
return Feed.objects.filter(id__in=result_ids)
|
||||||
|
|
||||||
|
|
||||||
class ContactsViewSet(viewsets.ReadOnlyModelViewSet):
|
class ContactsViewSet(ReadOnlyModelViewSet):
|
||||||
queryset = Occupation.objects.all()
|
queryset = Occupation.objects.all()
|
||||||
serializer_class = OccupationSerializer
|
serializer_class = OccupationSerializer
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
@@ -190,13 +202,13 @@ class ContactsViewSet(viewsets.ReadOnlyModelViewSet):
|
|||||||
return Occupation.by_year(int(year))
|
return Occupation.by_year(int(year))
|
||||||
|
|
||||||
|
|
||||||
class CommitteeViewSet(viewsets.ReadOnlyModelViewSet):
|
class CommitteeViewSet(ReadOnlyModelViewSet):
|
||||||
queryset = Committee.objects.all()
|
queryset = Committee.objects.all()
|
||||||
serializer_class = CommitteeSerializer
|
serializer_class = CommitteeSerializer
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
|
|
||||||
class TagsViewSet(viewsets.ReadOnlyModelViewSet):
|
class TagsViewSet(ReadOnlyModelViewSet):
|
||||||
queryset = Tag.objects.all()
|
queryset = Tag.objects.all()
|
||||||
serializer_class = TagSerializer
|
serializer_class = TagSerializer
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
|
|||||||
Reference in New Issue
Block a user