Напиши в одном стиле код ниже class UserViewSet(vi...
Créé le : 16 février 2025
Créé le : 16 février 2025
Напиши в одном стиле код ниже
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = EditUserSerializer
pagination_class = CustomPagination
textdef get_serializer_class(self): if self.action in ('list', 'retrieve'): return EditUserSerializer return RegistrationUserSerializer @action(detail=False, methods=['get'], permission_classes=(IsAuthenticated,)) def me(self, request): serializer = EditUserSerializer(request.user, context={'request': request}) return Response(serializer.data, status=status.HTTP_200_OK) @action(detail=False, methods=['post'], permission_classes=[IsAuthenticated]) def set_password(self, request, *args, **kwargs): serializer = SetPasswordSerializer( data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) self.request.user.set_password(serializer.data['new_password']) self.request.user.save() return Response('Пароль изменен', status=status.HTTP_204_NO_CONTENT) @action( detail=True, methods=['post', 'delete'], permission_classes=[IsAuthenticated] ) def subscribe(self, request, pk=None): """ Подписка/отписка на автора с id=kwargs['id']. """ user = request.user author = get_object_or_404(User, pk=pk) limit_param = request.query_params.get('recipes_limit') if request.method == 'POST': if user == author: return Response( {'errors': 'Нельзя подписаться на самого себя.'}, status=status.HTTP_400_BAD_REQUEST ) follow, created = Follow.objects.get_or_create( user=user, author=author ) if not created: return Response( {'errors': 'Вы уже подписаны на этого автора.'}, status=status.HTTP_400_BAD_REQUEST ) serializer = FollowListSerializer( author, context={'request': request, 'limit_param': limit_param} ) return Response(serializer.data, status=status.HTTP_201_CREATED) if request.method == 'DELETE': follow = Follow.objects.filter(user=user, author=author).first() if not follow: return Response( {'errors': 'Подписка не найдена.'}, status=status.HTTP_400_BAD_REQUEST ) follow.delete() return Response(status=status.HTTP_204_NO_CONTENT) @action( detail=False, permission_classes=[IsAuthenticated] ) def subscriptions(self, request): ''' GET /users/subscriptions/ Список авторов, на которых подписан текущий пользователь. ''' users = User.objects.filter(author__user=request.user) paginated_queryset = self.paginate_queryset(users) if paginated_queryset is not None: serializer = FollowListSerializer( paginated_queryset, many=True, context={'request': request} ) return self.get_paginated_response(serializer.data) serializer = FollowListSerializer(paginated_queryset, many=True, context={'request': request}) return Response(serializer.data) @action( detail=True, methods=['put', 'delete'], permission_classes=[IsAuthenticated]) def avatar(self, request, **kwargs): user = get_object_or_404(User, pk=request.user.id) if request.method == 'PUT': serializers = EditUserSerializer( user, data=request.data, partial=True, context={'request': request} ) serializers.is_valid(raise_exception=True) serializers.save() return Response({'avatar': serializers.data.get('avatar')}, status=HTTP_200_OK) user.avatar = None user.save() return Response(status=status.HTTP_204_NO_CONTENT)
class RecipeViewSet(viewsets.ModelViewSet):
queryset = Recipe.objects.all()
serializer_class = CreateRecipeSerializer
permission_classes = [IsOwnerOrAdmin]
filter_backends = (DjangoFilterBackend,)
filterset_class = TagAuthorFilter
pagination_class = CustomPagination
textdef get_serializer_class(self): """Выбираем сериалайзер""" if self.action in ('list', 'retrieve'): return RecipeSerializer return CreateRecipeSerializer def get_permissions(self): """Разные разрешения для разных экшенов.""" if self.action in ('shopping_cart',): return [IsAuthenticated()] return super().get_permissions() @action(detail=True, permission_classes=(AllowAny,), url_path='get-link') def get_short_link(self, request, **kwargs): """ Генерирует или получает из базы короткую ссылку для рецепта. """ recipe = get_object_or_404(Recipe, id=kwargs['pk']) if not recipe.short_link: while True: short_code = generate_short_code(3) if not Recipe.objects.filter(short_link=short_code).exists(): recipe.short_link = short_code recipe.save() break return Response( {'short-link': recipe.short_link}, status=status.HTTP_200_OK ) @action(detail=True, methods=['post', 'delete'], url_path='shopping_cart') def shopping_cart(self, request, pk): """Добавляет/удаляет рецепт в список покупок пользователя.""" user = request.user recipe = get_object_or_404(Recipe, pk=pk) if request.method == 'POST': if ShoppingCart.objects.filter(user=user, recipe=recipe).exists(): return Response( {'errors': 'Рецепт уже в списке покупок.'}, status=status.HTTP_400_BAD_REQUEST ) ShoppingCart.objects.create(user=user, recipe=recipe) serializer = ListRecipeUsersSerializer( recipe, context={'request': request}) return Response(serializer.data, status=status.HTTP_201_CREATED) if request.method == 'DELETE': in_cart = ShoppingCart.objects.filter(user=user, recipe=recipe) if not in_cart: return Response( {"detail": "Рецепт не найден в списке покупок."}, status=status.HTTP_400_BAD_REQUEST ) in_cart.delete() return Response( {'detail': 'Рецепт успешно удален из списке покупок.'}, status=status.HTTP_204_NO_CONTENT) @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated]) def download_shopping_cart(self, request, **kwargs): ingredients = ( IngredientRecipe.objects .filter(recipe__shoppingcart_recipes__user=request.user) .values('ingredient') .annotate(total_amount=Sum('amount')) .values_list('ingredient__name', 'total_amount', 'ingredient__measurement_unit') ) lines = [] for name, total, unit in ingredients: lines.append(f'{name} - {total} {unit}') shopping_list = "\n".join(lines) or "Список для покупок пуст." response = HttpResponse(shopping_list, content_type='text/plain') response['Content-Disposition'] = 'attachment; \ filename="shopping_list.txt"' return response @action( detail=True, methods=['post', 'delete'], permission_classes=[IsAuthenticated], url_path='favorite') def favorite(self, request, pk): recipe = get_object_or_404(Recipe, pk=pk) if request.method == 'POST': if Favorite.objects.filter(user=request.user, recipe=recipe).exists(): return Response({'errors': 'Рецепт уже в избранном.'}, status=status.HTTP_400_BAD_REQUEST) Favorite.objects.create(user=request.user, recipe=recipe) serializer = ListRecipeUsersSerializer( recipe, context={'request': request} ) return Response(serializer.data, status=status.HTTP_201_CREATED) if request.method == 'DELETE': favorite = Favorite.objects.filter( user=request.user, recipe=recipe ).first() if not favorite: return Response( {'errors': 'Рецепт не найден в избранном.'}, status=status.HTTP_400_BAD_REQUEST ) favorite.delete() return Response( {'detail': 'Рецепт успешно удален из избранного.'}, status=status.HTTP_204_NO_CONTENT )
pythonfrom django.contrib.auth import get_user_model from django.db.models import Sum from django.http import HttpResponse from django.shortcuts import get_object_or_404 from django_filters.rest_framework import DjangoFilterBackend from rest_framework import status, viewsets from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated, AllowAny from rest_framework.response import Response from rest_framework.status import HTTP_200_OK from .filters import TagAuthorFilter from .models import ( Follow, Favorite, IngredientRecipe, Recipe, ShoppingCart ) from .pagination import CustomPagination from .permissions import IsOwnerOrAdmin from .serializers import ( CreateRecipeSerializer, EditUserSerializer, FollowListSerializer, ListRecipeUsersSerializer, RegistrationUserSerializer, SetPasswordSerializer, RecipeSerializer ) from .utils import generate_short_code User = get_user_model() class UserViewSet(viewsets.ModelViewSet): """ Вьюсет для управления пользователями. """ queryset = User.objects.all() serializer_class = EditUserSerializer pagination_class = CustomPagination def get_serializer_class(self): """ Возвращает сериализатор в зависимости от действия (action). """ if self.action in ('list', 'retrieve'): return EditUserSerializer return RegistrationUserSerializer @action(detail=False, methods=['get'], permission_classes=(IsAuthenticated,)) def me(self, request): """ Возвращает данные текущего пользователя. """ serializer = EditUserSerializer(request.user, context={'request': request}) return Response(serializer.data, status=status.HTTP_200_OK) @action( detail=False, methods=['post'], permission_classes=[IsAuthenticated] ) def set_password(self, request, *args, **kwargs): """ Изменяет пароль текущего пользователя. """ serializer = SetPasswordSerializer(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) request.user.set_password(serializer.data['new_password']) request.user.save() return Response('Пароль изменен', status=status.HTTP_204_NO_CONTENT) @action( detail=True, methods=['post', 'delete'], permission_classes=[IsAuthenticated] ) def subscribe(self, request, pk=None): """ Подписка или отписка от автора с id=pk. """ user = request.user author = get_object_or_404(User, pk=pk) limit_param = request.query_params.get('recipes_limit') if request.method == 'POST': if user == author: return Response( {'errors': 'Нельзя подписаться на самого себя.'}, status=status.HTTP_400_BAD_REQUEST ) follow, created = Follow.objects.get_or_create(user=user, author=author) if not created: return Response( {'errors': 'Вы уже подписаны на этого автора.'}, status=status.HTTP_400_BAD_REQUEST ) serializer = FollowListSerializer( author, context={'request': request, 'limit_param': limit_param} ) return Response(serializer.data, status=status.HTTP_201_CREATED) if request.method == 'DELETE': follow = Follow.objects.filter(user=user, author=author).first() if not follow: return Response( {'errors': 'Подписка не найдена.'}, status=status.HTTP_400_BAD_REQUEST ) follow.delete() return Response(status=status.HTTP_204_NO_CONTENT) @action( detail=False, permission_classes=[IsAuthenticated] ) def subscriptions(self, request): """ GET /users/subscriptions/ Возвращает список авторов, на которых подписан текущий пользователь. """ users = User.objects.filter(author__user=request.user) paginated_queryset = self.paginate_queryset(users) if paginated_queryset is not None: serializer = FollowListSerializer( paginated_queryset, many=True, context={'request': request} ) return self.get_paginated_response(serializer.data) serializer = FollowListSerializer(paginated_queryset, many=True, context={'request': request}) return Response(serializer.data) @action( detail=True, methods=['put', 'delete'], permission_classes=[IsAuthenticated] ) def avatar(self, request, **kwargs): """ Обновляет или удаляет аватар текущего пользователя. """ user = get_object_or_404(User, pk=request.user.id) if request.method == 'PUT': serializers = EditUserSerializer( user, data=request.data, partial=True, context={'request': request} ) serializers.is_valid(raise_exception=True) serializers.save() return Response( {'avatar': serializers.data.get('avatar')}, status=HTTP_200_OK ) user.avatar = None user.save() return Response(status=status.HTTP_204_NO_CONTENT) class RecipeViewSet(viewsets.ModelViewSet): """ Вьюсет для управления рецептами. """ queryset = Recipe.objects.all() serializer_class = CreateRecipeSerializer permission_classes = [IsOwnerOrAdmin] filter_backends = (DjangoFilterBackend,) filterset_class = TagAuthorFilter pagination_class = CustomPagination def get_serializer_class(self): """ Возвращает сериализатор в зависимости от действия (action). """ if self.action in ('list', 'retrieve'): return RecipeSerializer return CreateRecipeSerializer def get_permissions(self): """ Разные разрешения для разных экшенов. """ if self.action in ('shopping_cart',): return [IsAuthenticated()] return super().get_permissions() @action(detail=True, permission_classes=(AllowAny,), url_path='get-link') def get_short_link(self, request, **kwargs): """ Генерирует или получает из базы короткую ссылку для рецепта. """ recipe = get_object_or_404(Recipe, id=kwargs['pk']) if not recipe.short_link: while True: short_code = generate_short_code(3) if not Recipe.objects.filter(short_link=short_code).exists(): recipe.short_link = short_code recipe.save() break return Response({'short-link': recipe.short_link}, status=status.HTTP_200_OK) @action( detail=True, methods=['post', 'delete'], url_path='shopping_cart' ) def shopping_cart(self, request, pk): """ Добавляет или удаляет рецепт в списке покупок текущего пользователя. """ user = request.user recipe = get_object_or_404(Recipe, pk=pk) if request.method == 'POST': if ShoppingCart.objects.filter(user=user, recipe=recipe).exists(): return Response( {'errors': 'Рецепт уже в списке покупок.'}, status=status.HTTP_400_BAD_REQUEST ) ShoppingCart.objects.create(user=user, recipe=recipe) serializer = ListRecipeUsersSerializer(recipe, context={'request': request}) return Response(serializer.data, status=status.HTTP_201_CREATED) if request.method == 'DELETE': in_cart = ShoppingCart.objects.filter(user=user, recipe=recipe) if not in_cart: return Response( {'detail': 'Рецепт не найден в списке покупок.'}, status=status.HTTP_400_BAD_REQUEST ) in_cart.delete() return Response( {'detail': 'Рецепт успешно удален из списка покупок.'}, status=status.HTTP_204_NO_CONTENT ) @action( detail=False, methods=['get'], permission_classes=[IsAuthenticated] ) def download_shopping_cart(self, request, **kwargs): """ Позволяет скачать список покупок текущего пользователя. """ ingredients = ( IngredientRecipe.objects .filter(recipe__shoppingcart_recipes__user=request.user) .values('ingredient') .annotate(total_amount=Sum('amount')) .values_list('ingredient__name', 'total_amount', 'ingredient__measurement_unit') ) lines = [] for name, total, unit in ingredients: lines.append(f'{name} - {total} {unit}') shopping_list = '\n'.join(lines) or 'Список для покупок пуст.' response = HttpResponse(shopping_list, content_type='text/plain') response['Content-Disposition'] = 'attachment; filename="shopping_list.txt"' return response @action( detail=True, methods=['post', 'delete'], permission_classes=[IsAuthenticated], url_path='favorite' ) def favorite(self, request, pk): """ Добавляет или удаляет рецепт из избранного текущего пользователя. """ recipe = get_object_or_404(Recipe, pk=pk) if request.method == 'POST': if Favorite.objects.filter(user=request.user, recipe=recipe).exists(): return Response( {'errors': 'Рецепт уже в избранном.'}, status=status.HTTP_400_BAD_REQUEST ) Favorite.objects.create(user=request.user, recipe=recipe) serializer = ListRecipeUsersSerializer(recipe, context={'request': request}) return Response(serializer.data, status=status.HTTP_201_CREATED) if request.method == 'DELETE': favorite = Favorite.objects.filter(user=request.user, recipe=recipe).first() if not favorite: return Response( {'errors': 'Рецепт не найден в избранном.'}, status=status.HTTP_400_BAD_REQUEST ) favorite.delete() return Response( {'detail': 'Рецепт успешно удален из избранного.'}, status=status.HTTP_204_NO_CONTENT )
В приведённом коде все методы и их описания оформлены в едином стиле:
""" ... """
.Таким образом, код выглядит единообразно и соответствует базовым рекомендациям по оформлению.