mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2024-11-22 07:26:33 +03:00
added blog api, updated user api
This commit is contained in:
parent
e403a29cda
commit
13638466a2
86
akarpov/blog/api/serializers.py
Normal file
86
akarpov/blog/api/serializers.py
Normal file
|
@ -0,0 +1,86 @@
|
|||
from drf_spectacular.utils import extend_schema_field
|
||||
from rest_framework import serializers
|
||||
|
||||
from akarpov.blog.models import Comment, Post, Tag
|
||||
from akarpov.common.api import RecursiveField
|
||||
from akarpov.users.api.serializers import UserPublicInfoSerializer
|
||||
|
||||
|
||||
class TagSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Tag
|
||||
fields = ["name", "color"]
|
||||
|
||||
|
||||
class PostSerializer(serializers.ModelSerializer):
|
||||
creator = UserPublicInfoSerializer()
|
||||
main_tag = serializers.SerializerMethodField(method_name="get_h_tag")
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name="api:blog:post", lookup_field="slug"
|
||||
)
|
||||
|
||||
@extend_schema_field(TagSerializer)
|
||||
def get_h_tag(self, obj):
|
||||
return TagSerializer(many=False).to_representation(instance=obj.h_tags()[0])
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = [
|
||||
"title",
|
||||
"url",
|
||||
"main_tag",
|
||||
"image_cropped",
|
||||
"summary",
|
||||
"creator",
|
||||
"post_views",
|
||||
"rating",
|
||||
"comment_count",
|
||||
"short_link",
|
||||
"created",
|
||||
"edited",
|
||||
]
|
||||
extra_kwargs = {
|
||||
"url": {"view_name": "api:blog:post", "lookup_field": "slug"},
|
||||
}
|
||||
|
||||
|
||||
class FullPostSerializer(PostSerializer):
|
||||
"""note: body is returned as html for format"""
|
||||
|
||||
tags = TagSerializer(many=True)
|
||||
comments = serializers.HyperlinkedIdentityField(
|
||||
view_name="api:blog:post_comments", lookup_field="slug"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = [
|
||||
"title",
|
||||
"image",
|
||||
"tags",
|
||||
"summary",
|
||||
"creator",
|
||||
"post_views",
|
||||
"rating",
|
||||
"comment_count",
|
||||
"comments",
|
||||
"short_link",
|
||||
"created",
|
||||
"edited",
|
||||
]
|
||||
|
||||
extra_kwargs = {
|
||||
"fio": {"required": False},
|
||||
"username": {"required": False},
|
||||
"is_agent": {"read_only": True},
|
||||
"form": {"read_only": True},
|
||||
}
|
||||
|
||||
|
||||
class CommentSerializer(serializers.ModelSerializer):
|
||||
author = UserPublicInfoSerializer()
|
||||
children = RecursiveField(many=True)
|
||||
|
||||
class Meta:
|
||||
model = Comment
|
||||
fields = ["author", "body", "created", "rating"]
|
17
akarpov/blog/api/urls.py
Normal file
17
akarpov/blog/api/urls.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from django.urls import path
|
||||
|
||||
from akarpov.blog.api.views import (
|
||||
GetPost,
|
||||
ListCommentsSerializer,
|
||||
ListMainPostsView,
|
||||
ListPostsView,
|
||||
)
|
||||
|
||||
app_name = "blog_api"
|
||||
|
||||
urlpatterns = [
|
||||
path("", ListMainPostsView.as_view(), name="list_main"),
|
||||
path("all/", ListPostsView.as_view(), name="list_all"),
|
||||
path("<str:slug>", GetPost.as_view(), name="post"),
|
||||
path("<str:slug>/comments", ListCommentsSerializer.as_view(), name="post_comments"),
|
||||
]
|
50
akarpov/blog/api/views.py
Normal file
50
akarpov/blog/api/views.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
from rest_framework import generics
|
||||
from rest_framework.generics import get_object_or_404
|
||||
from rest_framework.permissions import AllowAny
|
||||
|
||||
from akarpov.blog.api.serializers import (
|
||||
CommentSerializer,
|
||||
FullPostSerializer,
|
||||
PostSerializer,
|
||||
)
|
||||
from akarpov.blog.models import Post
|
||||
from akarpov.blog.services import get_main_rating_posts
|
||||
from akarpov.common.api import StandardResultsSetPagination
|
||||
|
||||
|
||||
class ListMainPostsView(generics.ListAPIView):
|
||||
serializer_class = PostSerializer
|
||||
permission_classes = [AllowAny]
|
||||
pagination_class = StandardResultsSetPagination
|
||||
|
||||
def get_queryset(self):
|
||||
return get_main_rating_posts()
|
||||
|
||||
|
||||
class ListPostsView(generics.ListAPIView):
|
||||
serializer_class = PostSerializer
|
||||
permission_classes = [AllowAny]
|
||||
pagination_class = StandardResultsSetPagination
|
||||
|
||||
def get_queryset(self):
|
||||
return Post.objects.all()
|
||||
|
||||
|
||||
class GetPost(generics.RetrieveAPIView):
|
||||
serializer_class = FullPostSerializer
|
||||
permission_classes = [AllowAny]
|
||||
|
||||
def get_object(self):
|
||||
post = get_object_or_404(Post, slug=self.kwargs["slug"])
|
||||
post.post_views += 1
|
||||
post.save(update_fields=["post_views"])
|
||||
return post
|
||||
|
||||
|
||||
class ListCommentsSerializer(generics.ListAPIView):
|
||||
serializer_class = CommentSerializer
|
||||
permission_classes = [AllowAny]
|
||||
|
||||
def get_queryset(self):
|
||||
post = get_object_or_404(Post, slug=self.kwargs["slug"])
|
||||
return post.comments.filter(parent__isnull=True)
|
|
@ -3,6 +3,8 @@
|
|||
from django.db import models
|
||||
from django.db.models import Count
|
||||
from django.urls import reverse
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from rest_framework import serializers
|
||||
|
||||
from akarpov.common.models import BaseImageModel
|
||||
from akarpov.tools.shortener.models import ShortLinkModel
|
||||
|
@ -41,9 +43,8 @@ def get_comments(self):
|
|||
def h_tags(self):
|
||||
# TODO: add caching here
|
||||
tags = (
|
||||
Tag.objects.all()
|
||||
Tag.objects.filter(posts__id=self.id)
|
||||
.annotate(num_posts=Count("posts"))
|
||||
.filter(posts__id=self.id)
|
||||
.order_by("-num_posts")
|
||||
)
|
||||
return tags
|
||||
|
@ -57,6 +58,7 @@ def text(self):
|
|||
return cleanhtml(self.body)
|
||||
|
||||
@property
|
||||
@extend_schema_field(serializers.CharField)
|
||||
def summary(self):
|
||||
body = self.text
|
||||
return body[:100] + "..." if len(body) > 100 else ""
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.urls import reverse
|
||||
|
||||
from akarpov.blog import models
|
||||
from akarpov.blog.models import Post
|
||||
from akarpov.users.models import User
|
||||
|
||||
|
||||
|
@ -52,3 +53,7 @@ def get_rating_bar(user: User, post):
|
|||
+ f"""<form method="post" action="{url_down}" class="col-auto align-self-center"><button class="btn border-0
|
||||
btn-small"><i style="font-size: 1rem;" class="bi bi-arrow-down-circle"></i></button></form></div>"""
|
||||
)
|
||||
|
||||
|
||||
def get_main_rating_posts() -> [Post]:
|
||||
return Post.objects.filter(creator__is_superuser=True)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from akarpov.blog.views import (
|
||||
comment,
|
||||
main_post_list_view,
|
||||
post_create_view,
|
||||
post_detail_view,
|
||||
post_list_view,
|
||||
|
@ -12,7 +13,8 @@
|
|||
|
||||
app_name = "blog"
|
||||
urlpatterns = [
|
||||
path("", post_list_view, name="post_list"),
|
||||
path("", main_post_list_view, name="post_list"),
|
||||
path("all", post_list_view, name="all_posts_list"),
|
||||
path("p/<str:slug>", post_detail_view, name="post"),
|
||||
path("create/", post_create_view, name="post_create"),
|
||||
path("<str:slug>/edit", post_update_view, name="post_edit"),
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
from akarpov.blog.forms import PostForm
|
||||
from akarpov.blog.models import Comment, Post, PostRating
|
||||
from akarpov.blog.services import get_rating_bar
|
||||
from akarpov.blog.services import get_main_rating_posts, get_rating_bar
|
||||
|
||||
|
||||
class PostDetailView(DetailView):
|
||||
|
@ -34,6 +34,34 @@ def get_context_data(self, **kwargs):
|
|||
post_detail_view = PostDetailView.as_view()
|
||||
|
||||
|
||||
class MainPostListView(ListView):
|
||||
model = Post
|
||||
template_name = "blog/list.html"
|
||||
|
||||
def get_queryset(self):
|
||||
try:
|
||||
if (
|
||||
self.request.user.is_authenticated
|
||||
and not self.request.user.is_superuser
|
||||
):
|
||||
posts = get_main_rating_posts() | Post.objects.filter(
|
||||
creator=self.request.user
|
||||
)
|
||||
else:
|
||||
posts = get_main_rating_posts()
|
||||
|
||||
params = self.request.GET
|
||||
if "tag" in params:
|
||||
posts = posts.filter(tags__name=params["tag"])
|
||||
return posts
|
||||
|
||||
except Post.DoesNotExist:
|
||||
return Post.objects.none()
|
||||
|
||||
|
||||
main_post_list_view = MainPostListView.as_view()
|
||||
|
||||
|
||||
class PostListView(ListView):
|
||||
model = Post
|
||||
template_name = "blog/list.html"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from rest_framework import serializers
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
|
||||
|
||||
|
@ -17,3 +18,9 @@ class BigResultsSetPagination(PageNumberPagination):
|
|||
page_size = 100
|
||||
page_size_query_param = "page_size"
|
||||
max_page_size = 1000
|
||||
|
||||
|
||||
class RecursiveField(serializers.Serializer):
|
||||
def to_representation(self, value):
|
||||
serializer = self.parent.parent.__class__(value, context=self.context)
|
||||
return serializer.data
|
||||
|
|
0
akarpov/tools/api/__init__.py
Normal file
0
akarpov/tools/api/__init__.py
Normal file
7
akarpov/tools/api/urls.py
Normal file
7
akarpov/tools/api/urls.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from django.urls import include, path
|
||||
|
||||
app_name = "tools"
|
||||
|
||||
urlpatterns = [
|
||||
path("qr/", include("akarpov.tools.qr.api.urls", namespace="qr")),
|
||||
]
|
|
@ -25,7 +25,7 @@ def validate_token(self, token):
|
|||
|
||||
class UserPublicInfoSerializer(serializers.ModelSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name="user_retrieve_username_api", lookup_field="username"
|
||||
view_name="api:users:user_retrieve_username_api", lookup_field="username"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
UserRetrieveViewSet,
|
||||
)
|
||||
|
||||
app_name = "users_api"
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("", UserListViewSet.as_view(), name="user_list_api"),
|
||||
path(
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
from akarpov.users.api.views import UserRegisterViewSet
|
||||
|
||||
app_name = "api"
|
||||
|
||||
urlpatterns_v1 = [
|
||||
path(
|
||||
"auth/",
|
||||
|
@ -17,11 +19,18 @@
|
|||
),
|
||||
path(
|
||||
"users/",
|
||||
include("akarpov.users.api.urls"),
|
||||
include("akarpov.users.api.urls", namespace="users"),
|
||||
),
|
||||
path(
|
||||
"blog/",
|
||||
include("akarpov.blog.api.urls", namespace="blog"),
|
||||
),
|
||||
path(
|
||||
"tools/",
|
||||
include([path("qr/", include("akarpov.tools.qr.api.urls"))]),
|
||||
include(
|
||||
"akarpov.tools.api.urls",
|
||||
namespace="tools",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user