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
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,23 @@ Yamdb. Клиент может получить только разрешенн
```
python manage.py fill_db -m [Model] -f [file]
```
Важно отметить, что название модели нужно вводить строго
с заглавной буквы. Так же для заполнения БД необходимо по следующем критериям:
1. Первым делом заполнить модель User;
2. Заполнить модели Category / Genre;
3. Заполнить модель Title;
4. Заполнить модель GenreTitle;
5. Последующие модели.
Если не учесть данную последовательность, то возникнет ошибка,
т.к. все модели с полями ForeignKey / ManyToManyField ожидают
экземпляр класса связующей ею моделью.

Просьба - учесть данный факт!

### Пример команды
```
python manage.py fill_db -m Category -f category
```
Для подробной информации используйте:
```
python manage.py fill_db -h
Expand Down
49 changes: 23 additions & 26 deletions api_yamdb/api/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,48 @@
from rest_framework.permissions import SAFE_METHODS, BasePermission


class OwnerOrAdmins(permissions.BasePermission):
class PermissionAdmins(permissions.BasePermission):

def has_permission(self, request, view):
return (
request.user.is_authenticated
and (
request.user.is_admin
or request.user.is_superuser)
request.user.is_authenticated
and (
request.user.is_admin
or request.user.is_superuser
or request.user.is_staff
)
)

def has_object_permission(self, request, view, obj):
return (
obj == request.user
or request.user.is_admin
or request.user.is_superuser)


class IsAdminOrReadOnly(BasePermission):
"""Разрешение на уровне админ."""

def has_permission(self, request, view):
return (
request.method in SAFE_METHODS
or (
request.user.is_authenticated
and request.user.is_admin
)
request.method in SAFE_METHODS
or (
request.user.is_authenticated
and request.user.is_admin
)
)


class AuthorAndStaffOrReadOnly(BasePermission):
class ModeratorReadOnly(BasePermission):
def has_permission(self, request, view):
return (
request.method in SAFE_METHODS
or request.user.is_authenticated
request.method in SAFE_METHODS
or request.user.is_authenticated
)

def has_object_permission(self, request, view, obj):
return (
request.method in SAFE_METHODS
or (
request.user.is_authenticated
and (
obj.author == request.user
or request.user.is_moderator
request.method in SAFE_METHODS
or (
request.user.is_authenticated
and (
obj.author == request.user
or request.user.is_moderator
or request.user.is_admin
)
)
)
)
18 changes: 7 additions & 11 deletions api_yamdb/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import datetime as dt
from django.core.validators import MaxValueValidator, MinValueValidator
from rest_framework import serializers
from rest_framework.relations import SlugRelatedField

Expand All @@ -9,15 +9,16 @@
Review,
Title,
)
from reviews.validators import validate_year
from users.models import User


class SignUpSerializer(serializers.Serializer):
email = serializers.EmailField(max_length=254, required=True)
username = serializers.CharField(max_length=150, required=True)

def validate(self, data):
if data['username'] == 'me':
def validate_username(self, data):
if data.lower() == 'me':
raise serializers.ValidationError('Нельзя использовать логин me')
return data

Expand All @@ -29,9 +30,6 @@ class TokenSerializer(serializers.Serializer):
username = serializers.CharField(max_length=150, required=True)
confirmation_code = serializers.CharField(required=True)

class Meta:
fields = ('username', 'confirmation_code')


class UserSerializer(serializers.ModelSerializer):
class Meta:
Expand Down Expand Up @@ -95,9 +93,7 @@ class Meta:
model = Title

def validate_year(self, value):
current_year = dt.date.today().year
if value > current_year:
raise serializers.ValidationError('Проверьте год')
validate_year(value)
return value


Expand Down Expand Up @@ -156,8 +152,8 @@ def validate(self, data):
return data

def validate_score(self, value):
if 0 >= value >= 10:
raise serializers.ValidationError('Проверьте оценку')
MaxValueValidator(value),
MinValueValidator(value)
return value


Expand Down
8 changes: 4 additions & 4 deletions api_yamdb/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@
router.register('genres', GenresViewSet, basename='genres')
router.register('categories', CategoriesViewSet, basename='categories')
router.register(
r'titles/(?P<title_id>[\d]+)/reviews',
r'titles/(?P<title_id>\d+)/reviews',
ReviewViewSet,
basename='reviews'
)

router.register(
r'titles/(?P<title_id>[\d]+)/reviews/(?P<review_id>[\d]+)/comments',
r'titles/(?P<title_id>\d+)/reviews/(?P<review_id>\d+)/comments',
CommentViewSet,
basename='comments',
)
urlpatterns = [
path('v1/auth/token/', token_post),
path('v1/auth/signup/', signup_post),
path('v1/auth/token/', token_post, name='token'),
path('v1/auth/signup/', signup_post, name='signup'),
path('v1/', include(router.urls)),
]
35 changes: 14 additions & 21 deletions api_yamdb/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from users.models import User
from api.paginator import CommentPagination
from api.filters import TitleFilter
from api.permissions import (AuthorAndStaffOrReadOnly,
IsAdminOrReadOnly, OwnerOrAdmins)
from api.permissions import (ModeratorReadOnly,
IsAdminOrReadOnly, PermissionAdmins)
from api.serializers import (CategoriesSerializer,
CommentsSerializer, GenresSerializer,
ReviewsSerializer, SignUpSerializer,
Expand Down Expand Up @@ -45,7 +45,8 @@ def signup_post(request):
user.confirmation_code = confirmation_code
user.save()
send_mail(
'Код подверждения', confirmation_code,
'Confirmation code',
f'Ваш код подтверждения для получения токена: {confirmation_code}',
['admin@email.com'], (email, ), fail_silently=False
)
return Response(serializer.data, status=status.HTTP_200_OK)
Expand All @@ -67,7 +68,7 @@ def token_post(request):
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('id')
serializer_class = UserSerializer
permission_classes = (OwnerOrAdmins, )
permission_classes = (PermissionAdmins, )
filter_backends = (filters.SearchFilter, )
filterset_fields = ('username')
search_fields = ('username', )
Expand All @@ -93,7 +94,7 @@ def get_patch_me(self, request):

class TitlesViewSet(viewsets.ModelViewSet):
queryset = Title.objects.annotate(
rating=Avg('reviews__score')).order_by('id')
rating=Avg('reviews__score'))
serializer_class = TitlesSerializer
permission_classes = [IsAdminOrReadOnly]
filterset_class = TitleFilter
Expand Down Expand Up @@ -122,24 +123,23 @@ class ReviewGenreModelMixin(


class CategoriesViewSet(ReviewGenreModelMixin):
queryset = Category.objects.all().order_by('id')
queryset = Category.objects.all()
serializer_class = CategoriesSerializer


class GenresViewSet(ReviewGenreModelMixin):
queryset = Genre.objects.all().order_by('id')
queryset = Genre.objects.all()
serializer_class = GenresSerializer


class ReviewViewSet(viewsets.ModelViewSet):
serializer_class = ReviewsSerializer
pagination_class = CommentPagination
permission_classes = [AuthorAndStaffOrReadOnly]
permission_classes = [ModeratorReadOnly]

def get_queryset(self):
title = get_object_or_404(Title, id=self.kwargs.get('title_id'))
new_queryset = title.reviews.all()
return new_queryset
return title.reviews.all()

def perform_create(self, serializer):
title = get_object_or_404(Title, id=self.kwargs.get('title_id'))
Expand All @@ -149,21 +149,14 @@ def perform_create(self, serializer):
class CommentViewSet(viewsets.ModelViewSet):
serializer_class = CommentsSerializer
pagination_class = CommentPagination
permission_classes = [AuthorAndStaffOrReadOnly]
permission_classes = [ModeratorReadOnly]

def get_queryset(self):
title = get_object_or_404(Title, id=self.kwargs.get('title_id'))
try:
review = title.reviews.get(id=self.kwargs.get('review_id'))
except TypeError:
TypeError('У произведения нет такого отзыва')
queryset = review.comments.all().order_by('-pub_date')
return queryset
review = title.reviews.get(id=self.kwargs.get('review_id'))
return review.comments.all()

def perform_create(self, serializer):
title = get_object_or_404(Title, id=self.kwargs.get('title_id'))
try:
review = title.reviews.get(id=self.kwargs.get('review_id'))
except TypeError:
TypeError('У произведения нет такого отзыва')
review = title.reviews.get(id=self.kwargs.get('review_id'))
serializer.save(author=self.request.user, review=review)
90 changes: 0 additions & 90 deletions api_yamdb/reviews/migrations/0001_initial.py

This file was deleted.

Loading