diff --git a/backend/api/posts/serializers.py b/backend/api/posts/serializers.py index 54b3d6d..0f2e6ec 100644 --- a/backend/api/posts/serializers.py +++ b/backend/api/posts/serializers.py @@ -1,3 +1,4 @@ +from typing import Any, Dict, List, Optional from rest_framework import serializers from django.utils.timezone import localtime @@ -5,21 +6,6 @@ from django.utils.timezone import localtime from apps.archive.models import PostModel -class PostListSerializer(serializers.Serializer): - count = serializers.SerializerMethodField() - posts = serializers.SerializerMethodField() - - class Meta: - model = PostModel - fields = ["count", "posts"] - - def get_count(self, obj): - return obj.count() - - def get_posts(self, obj): - return PostPreviewSerializer(obj.all(), many=True).data - - class PostPreviewSerializer(serializers.ModelSerializer): description = serializers.SerializerMethodField() date = serializers.SerializerMethodField() @@ -44,46 +30,37 @@ class PostPreviewSerializer(serializers.ModelSerializer): "tags", ] - def get_description(self, obj): - return obj.description.first().content + def get_description(self, obj: PostModel) -> Optional[str]: + return obj.description.first().content if obj.description.exists() else None - def get_source_site(self, obj): + def get_source_site(self, obj: PostModel) -> Dict[str, str]: return { "slug": obj.source_site.slug, "name": obj.source_site.name, } - def get_category(self, obj): - data = [] - for i in obj.category.all(): - data.append({"slug": i.slug, "name": i.name}) - return data - - def get_creator(self, obj): - avatar_url = None - if obj.creator.avatar: - avatar_url = obj.creator.avatar.file.url + def get_category(self, obj: PostModel) -> List[Dict[str, str]]: + return [{"slug": i.slug, "name": i.name} for i in obj.category.all()] + def get_creator(self, obj: PostModel) -> Dict[str, Optional[str]]: + avatar_url = obj.creator.avatar.file.url if obj.creator.avatar else None return { "slug": obj.creator.slug, "name": obj.creator.name, "avatar": avatar_url, } - def get_date(self, obj): + def get_date(self, obj: PostModel) -> Dict[str, str]: return { "created": localtime(obj.date_created).isoformat(), "imported": localtime(obj.date_imported).isoformat(), "last_import": localtime(obj.date_last_import).isoformat(), } - def get_media(self, obj): - data = [] - for i in obj.files.all(): - data.append({"type": i.mimetype, "src": i.file.url}) - return data + def get_media(self, obj: PostModel) -> List[Dict[str, str]]: + return [{"type": i.mimetype, "src": i.file.url} for i in obj.files.all()] - def get_tags(self, obj): + def get_tags(self, obj: PostModel) -> List[str]: return [tag.slug for tag in obj.tags.all()] @@ -109,39 +86,35 @@ class PostSerializer(serializers.ModelSerializer): "tags", ] - def get_source_site(self, obj): + def get_source_site(self, obj) -> Dict[str, str]: return { "slug": obj.source_site.slug, "name": obj.source_site.name, } - def get_description(self, obj): + def get_description(self, obj) -> Dict[str, str]: return { "count": obj.description.count(), "content": obj.description.first().content, } - def get_creator(self, obj): + def get_creator(self, obj) -> Dict[str, str]: return { "slug": obj.creator.slug, "name": obj.creator.name, - # "source_site": { - # "slug": obj.creator.source_site.slug, - # "name": obj.creator.source_site.name, - # }, } - def get_tags(self, obj): + def get_tags(self, obj) -> List[str]: return [tag.slug for tag in obj.tags.all()] - def get_date(self, obj): + def get_date(self, obj) -> Dict[str, str]: return { "created": localtime(obj.date_created).isoformat(), "imported": localtime(obj.date_imported).isoformat(), "last_import": localtime(obj.date_last_import).isoformat(), } - def get_media(self, obj): + def get_media(self, obj) -> List[Dict[str, str]]: data = [] for i in obj.files.all(): data.append({"type": i.mimetype, "url": i.file.url}) diff --git a/backend/api/posts/urls.py b/backend/api/posts/urls.py index 41c92a6..faf9644 100644 --- a/backend/api/posts/urls.py +++ b/backend/api/posts/urls.py @@ -1,8 +1,8 @@ from django.urls import path -from api.posts.views import PostView, PostListView +from api.posts.views import PostDetailView, PostListView urlpatterns = [ - path("/", PostView.as_view(), name="post_details"), + path("/", PostDetailView.as_view(), name="post_detail"), path("", PostListView.as_view(), name="post_list"), ] diff --git a/backend/api/posts/views.py b/backend/api/posts/views.py index 03f08df..c267f69 100644 --- a/backend/api/posts/views.py +++ b/backend/api/posts/views.py @@ -1,34 +1,42 @@ +from rest_framework import generics from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated from apps.archive.models import PostModel -from .serializers import PostListSerializer, PostSerializer +from .serializers import PostPreviewSerializer, PostSerializer -class PostListView(APIView): +class PostListView(generics.ListAPIView): permission_classes = [IsAuthenticated] + serializer_class = ( + PostPreviewSerializer # Each post will be serialized using this serializer + ) - def get(self, request): - user = request.user.userprofile - + def get_queryset(self): + user = self.request.user.userprofile if user.show_mature: - posts = PostModel.objects.all().order_by("-date_created") + queryset = PostModel.objects.all() else: - posts = PostModel.objects.filter(mature=False).order_by("-date_created") - serializer = PostListSerializer(posts) - return Response(serializer.data) + queryset = PostModel.objects.filter(mature=False) + return queryset.order_by("-date_created") + + def list(self, request, *args, **kwargs): + """ + Overriding list() allows us to return a custom response structure, + for example including a count and a key 'posts' instead of DRF's default 'results'. + """ + queryset = self.filter_queryset(self.get_queryset()) + serializer = self.get_serializer(queryset, many=True) + data = {"count": queryset.count(), "posts": serializer.data} + return Response(data) -class PostView(APIView): +class PostDetailView(generics.RetrieveAPIView): permission_classes = [IsAuthenticated] - - def get(self, request, post_id): - try: - post_instance = PostModel.objects.get(post_id=post_id) - except PostModel.DoesNotExist: - raise NotFound(detail="Post not found.") - - serializer = PostSerializer(post_instance) - return Response(serializer.data) + serializer_class = PostSerializer + lookup_field = ( + "post_id" # This tells DRF to use the "post_id" URL kwarg for lookups. + ) + queryset = PostModel.objects.all()