diff --git a/.idea/BlogProject.iml b/.idea/BlogProject.iml index 92de0e4..8a24ab6 100644 --- a/.idea/BlogProject.iml +++ b/.idea/BlogProject.iml @@ -16,7 +16,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index a6c6116..c0ac767 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/Blog/serializer.py b/Blog/serializer.py new file mode 100644 index 0000000..9963870 --- /dev/null +++ b/Blog/serializer.py @@ -0,0 +1,14 @@ +from rest_framework import serializers +from Blog.models import Post, Comment + + +class PostSerializer(serializers.ModelSerializer): + class Meta: + model = Post + fields = ['title', 'content', 'author', 'publ_date', 'category'] + +class CommentSerializer(serializers.ModelSerializer): + class Meta: + model = Comment + fields = ['post', 'author_of_the_comment', 'content_of_the_comment', 'date_of_creation'] + diff --git a/Blog/urls.py b/Blog/urls.py new file mode 100644 index 0000000..6cb9b44 --- /dev/null +++ b/Blog/urls.py @@ -0,0 +1,14 @@ +from django.urls import path, include +from . import views + +from rest_framework.urlpatterns import format_suffix_patterns + +urlpatterns = [ + path('post/', views.PostList.as_view()), + path('post//', views.PostDetail.as_view()), + path('comment/', views.CommentList.as_view()), + path('comment//', views.CommentDetail.as_view()), + path('drf-auth', include('rest_framework.urls')), +] + +urlpatterns = format_suffix_patterns(urlpatterns) \ No newline at end of file diff --git a/Blog/views.py b/Blog/views.py index 91ea44a..f354b97 100644 --- a/Blog/views.py +++ b/Blog/views.py @@ -1,3 +1,170 @@ from django.shortcuts import render +from drf_yasg.utils import swagger_auto_schema +from rest_framework.permissions import IsAuthenticatedOrReadOnly + +from .models import Post, Comment +from .serializer import PostSerializer, CommentSerializer +from django.http import Http404 +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import status +from drf_yasg import openapi + +class PostList(APIView): + permission_classes = [IsAuthenticatedOrReadOnly] + + @swagger_auto_schema( + operation_description="Get a list of posts", + responses={200: openapi.Response('List of posts', PostSerializer(many=True))} + ) + def get(self, request, format=None): + post = Post.objects.all() + serializer = PostSerializer(post, many=True) + return Response(serializer.data) + + @swagger_auto_schema( + operation_description="Create a new post", + request_body=PostSerializer, + responses={201: 'Created', 400: 'Bad Request'} + ) + + def post(self, request, format=None): + serializer = PostSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class PostDetail(APIView): + permission_classes = [IsAuthenticatedOrReadOnly] + + def get_object(self, pk): + try: + return Post.objects.get(pk=pk) + except Post.DoesNotExist: + raise Http404 + + @swagger_auto_schema( + operation_description="Get details of a specific post", + manual_parameters=[ + openapi.Parameter('pk', openapi.IN_PATH, description="Post ID", type=openapi.TYPE_INTEGER), + ], + responses={200: openapi.Response('Post details', PostSerializer)} + ) + + def get(self, request, pk, format=None): + post = self.get_object(pk) + serializer = PostSerializer(post) + return Response(serializer.data) + + @swagger_auto_schema( + operation_description="Update details of a specific post", + manual_parameters=[ + openapi.Parameter('pk', openapi.IN_PATH, description="Post ID", type=openapi.TYPE_INTEGER), + ], + request_body=PostSerializer, + responses={200: 'Updated', 400: 'Bad Request'} + ) + + def put(self, request, pk, format=None): + post = self.get_object(pk) + serializer = PostSerializer(post, data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + @swagger_auto_schema( + operation_description="Delete a specific post", + manual_parameters=[ + openapi.Parameter('pk', openapi.IN_PATH, description="Post ID", type=openapi.TYPE_INTEGER), + ], + responses={204: 'No Content'} + ) + + def delete(self, request, pk, format=None): + post = self.get_object(pk) + post.delete() + return Response(status=status.HTTP_204_NO_CONTENT) + + +class CommentList(APIView): + permission_classes = [IsAuthenticatedOrReadOnly] + + @swagger_auto_schema( + operation_description="Get a list of comments", + responses={200: openapi.Response('List of comments', CommentSerializer(many=True))} + ) + + def get(self, request, format=None): + comment = Comment.objects.all() + serializer = CommentSerializer(comment, many=True) + return Response(serializer.data) + + @swagger_auto_schema( + operation_description="Create a new comment", + request_body=CommentSerializer, + responses={201: 'Created', 400: 'Bad Request'} + ) + + def post(self, request, format=None): + serializer = CommentSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class CommentDetail(APIView): + permission_classes = [IsAuthenticatedOrReadOnly] + + def get_object(self, pk): + try: + return Comment.objects.get(pk=pk) + except Comment.DoesNotExist: + raise Http404 + + @swagger_auto_schema( + operation_description="Get details of a specific comment", + manual_parameters=[ + openapi.Parameter('pk', openapi.IN_PATH, description="Comment ID", type=openapi.TYPE_INTEGER), + ], + responses={200: openapi.Response('Comment details', CommentSerializer)} + ) + + def get(self, request, pk, format=None): + comment = self.get_object(pk) + serializer = CommentSerializer(comment) + return Response(serializer.data) + + @swagger_auto_schema( + operation_description="Update details of a specific comment", + manual_parameters=[ + openapi.Parameter('pk', openapi.IN_PATH, description="Comment ID", type=openapi.TYPE_INTEGER), + ], + request_body=CommentSerializer, + responses={200: 'Updated', 400: 'Bad Request'} + + ) + + def put(self, request, pk, format=None): + comment = self.get_object(pk) + serializer = CommentSerializer(comment, data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + @swagger_auto_schema( + operation_description="Delete a specific comment", + manual_parameters=[ + openapi.Parameter('pk', openapi.IN_PATH, description="Comment ID", type=openapi.TYPE_INTEGER), + ], + responses={204: 'No Content'} + ) + + def delete(self, request, pk, format=None): + comment = self.get_object(pk) + comment.delete() + return Response(status=status.HTTP_204_NO_CONTENT) + -# Create your views here. diff --git a/BlogProject/settings.py b/BlogProject/settings.py index 9bf9d7d..20ad7ae 100644 --- a/BlogProject/settings.py +++ b/BlogProject/settings.py @@ -1,14 +1,3 @@ -""" -Django settings for BlogProject project. - -Generated by 'django-admin startproject' using Django 4.2.6. - -For more information on this file, see -https://docs.djangoproject.com/en/4.2/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/4.2/ref/settings/ -""" from pathlib import Path @@ -38,6 +27,9 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'Blog', + 'rest_framework', + 'drf_yasg', + ] MIDDLEWARE = [ @@ -123,3 +115,10 @@ # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework.authentication.BasicAuthentication', + 'rest_framework.authentication.SessionAuthentication', + ] +} \ No newline at end of file diff --git a/BlogProject/urls.py b/BlogProject/urls.py index ce890c3..3a4e885 100644 --- a/BlogProject/urls.py +++ b/BlogProject/urls.py @@ -1,22 +1,12 @@ -""" -URL configuration for BlogProject project. - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/4.2/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" from django.contrib import admin -from django.urls import path +from django.urls import path, re_path, include +from .yasg import urlpatterns as doc_urls + urlpatterns = [ path('admin/', admin.site.urls), + path('api/', include([ + path('blog/', include('Blog.urls')), + ])), ] +urlpatterns += doc_urls \ No newline at end of file diff --git a/BlogProject/yasg.py b/BlogProject/yasg.py new file mode 100644 index 0000000..b5588d9 --- /dev/null +++ b/BlogProject/yasg.py @@ -0,0 +1,21 @@ +from django.urls import re_path, path +from rest_framework import permissions +from drf_yasg.views import get_schema_view +from drf_yasg import openapi + +schema_view = get_schema_view( + openapi.Info( + title="Snippets API", + default_version='v1', + description="Test description", + license=openapi.License(name="BSD License"), + ), + public=True, + permission_classes=(permissions.AllowAny,), +) + +urlpatterns = [ + path('swagger/', schema_view.without_ui(cache_timeout=0), name='schema-json'), + path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), + path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), +] \ No newline at end of file diff --git a/db.sqlite3 b/db.sqlite3 index ae05419..3137b22 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fa5e2a5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +Django~=4.2.6 +djangorestframework==3.14.0 +drf-yasg==1.21.7