Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/BlogProject.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Blog/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from django.contrib import admin

from django.contrib import admin
from .models import Post, Comment
Expand Down
1 change: 1 addition & 0 deletions Blog/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.db import models
from django.contrib.auth.models import User


class Post(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
Expand Down
62 changes: 62 additions & 0 deletions Blog/serializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from Blog.models import Post, Comment
from rest_framework import serializers
from django.contrib.auth.models import User

class UserRegistrationSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)

class Meta:
model = User
fields = ['email', 'first_name', 'last_name', 'password']

def validate_email(self, value):
# Кастомна валідація для формату електронної пошти
if not value.endswith('@gmail.com'):
raise serializers.ValidationError('Електронна пошта повинна закінчуватися на @gmail.com.')
return value

def validate_password(self, value):
# Кастомна валідація для паролю (наприклад, довжина паролю)
if len(value) < 8:
raise serializers.ValidationError('Пароль повинен бути не менше 8 символів.')
return value

def validate(self, data):
# Перевірка, чи користувач з таким ім'ям вже існує
username = data.get('email')
if User.objects.filter(username=username).exists():
raise serializers.ValidationError('Користувач з таким іменем вже існує.')
return data
def create(self, validated_data):
validated_data['username'] = validated_data['email']
user = User.objects.create_user(**validated_data)
return user

class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'email', 'password')

def validate_email(self, value):
# Кастомна валідація для формату електронної пошти
if not value.endswith('@gmail.com'):
raise serializers.ValidationError('Електронна пошта повинна закінчуватися на @gmail.com.')
return value

def validate_username(self, value):
# Кастомна валідація для унікальності імені користувача
if User.objects.filter(username=value).exists():
raise serializers.ValidationError('Користувач з таким іменем вже існує.')
return value


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']

88 changes: 87 additions & 1 deletion Blog/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,89 @@
from django.test import TestCase
from rest_framework.test import APITestCase

from .models import User
from .serializer import UserRegistrationSerializer


class UserRegistrationAPITests(APITestCase):

def setUp(self):
self.valid_data = {
'email': 'test@gmail.com',
'first_name': 'Test',
'last_name': 'User',
'password': '12345678',
}

def test_registration_success(self):
response = self.client.post('/api/blog/register/', data=self.valid_data)
self.assertEqual(response.status_code, 201)

user = User.objects.get(email='test@gmail.com')
self.assertEqual(user.first_name, 'Test')
self.assertEqual(user.last_name, 'User')
self.assertTrue(user.check_password('12345678'))

def test_registration_with_invalid_email(self):
invalid_data = self.valid_data.copy()
invalid_data['email'] = 'test'
response = self.client.post('/api/blog/register/', data=invalid_data)
self.assertEqual(response.status_code, 400)

# Перевірка наявності 'email' у відповіді
self.assertIn('email', response.json())

# Перевірка тексту помилки, використовуючи 'in'
expected_error = 'Enter a valid email address.'
actual_error = response.json()['email'][0]
self.assertIn(expected_error, actual_error)

def test_registration_with_too_short_password(self):
invalid_data = self.valid_data.copy()
invalid_data['password'] = '123'
response = self.client.post('/api/blog/register/', data=invalid_data)
self.assertEqual(response.status_code, 400)

# Перевірка наявності 'password' у відповіді
self.assertIn('password', response.json())

# Перевірка тексту помилки
self.assertEqual(response.json()['password'][0], 'Пароль повинен бути не менше 8 символів.')

def test_registration_with_existing_username(self):
self.client.post('/api/blog/register/', data=self.valid_data)
response = self.client.post('/api/blog/register/', data=self.valid_data)
self.assertEqual(response.status_code, 400)

# Перевірка наявності 'non_field_errors' у відповіді
self.assertIn('non_field_errors', response.json())

# Перевірка тексту помилки для 'non_field_errors'
expected_error = 'Користувач з таким іменем вже існує.'
actual_error = response.json()['non_field_errors'][0]
self.assertIn(expected_error, actual_error)

def test_registration_with_non_gmail_email(self):
invalid_data = self.valid_data.copy()
invalid_data['email'] = 'test@yahoo.com'
response = self.client.post('/api/blog/register/', data=invalid_data)
self.assertEqual(response.status_code, 400)

# Перевірка наявності 'email' у відповіді
self.assertIn('email', response.json())

# Перевірка тексту помилки для 'email'
expected_error = 'Електронна пошта повинна закінчуватися на @gmail.com.'
actual_error = response.json()['email'][0]
self.assertIn(expected_error, actual_error)

def test_registration_with_valid_email(self):
valid_data = self.valid_data.copy()
valid_data['email'] = 'test@gmail.com'
response = self.client.post('/api/blog/register/', data=valid_data)
self.assertEqual(response.status_code, 201)

# Перевірка, що користувач був успішно створений
user = User.objects.get(email='test@gmail.com')
self.assertEqual(user.email, 'test@gmail.com')

# Create your tests here.
20 changes: 20 additions & 0 deletions Blog/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from django.urls import path, include, re_path
from . import views
from .views import register_user

from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = [
path('post/', views.PostList.as_view()),
path('post/<int:pk>/', views.PostDetail.as_view()),
path('comment/', views.CommentList.as_view()),
path('comment/<int:pk>/', views.CommentDetail.as_view()),
path('drf-auth/', include('rest_framework.urls')), #в гуглі
path('register/', register_user, name='register_user'), # в postman
#path('auth/', include('djoser.urls')),
#path('auth/', include('djoser.urls.authtoken')),


]

urlpatterns = format_suffix_patterns(urlpatterns)
180 changes: 178 additions & 2 deletions Blog/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,179 @@
from django.shortcuts import render
from drf_yasg.utils import swagger_auto_schema
from rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAdminUser
from .models import Post, Comment
from .serializer import PostSerializer, CommentSerializer
from django.http import Http404
from rest_framework.views import APIView
from drf_yasg import openapi
from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view
from .serializer import UserRegistrationSerializer

@api_view(['POST'])
def register_user(request):
serializer = UserRegistrationSerializer(data=request.data)

if serializer.is_valid():
serializer.save()
return Response({'message': 'User registered successfully'}, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

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 = [IsAdminUser]

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 = [IsAdminUser]
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.
Loading