-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
change views. delete from favorites and cart
- Loading branch information
root
committed
Mar 22, 2024
1 parent
90715b2
commit d1eb50e
Showing
3 changed files
with
216 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
import csv | ||
|
||
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 djoser.views import UserViewSet | ||
from rest_framework import filters, status, viewsets | ||
from rest_framework.decorators import action | ||
from rest_framework.exceptions import AuthenticationFailed | ||
from rest_framework.permissions import (IsAuthenticated, | ||
IsAuthenticatedOrReadOnly) | ||
from rest_framework.response import Response | ||
|
||
from api.filter import RecipeFilter | ||
from api.pagination import CustomPaginator | ||
from api.permissions import AdminOrReadOnly, AuthorAdminOrReadOnly | ||
from api.serializers import (AddToRecipeSerializer, CustomUserSerializer, | ||
IngredientSerializer, RecipeCreateSerializer, | ||
RecipeGetSerializer, SubscriptionsSerializer, | ||
TagSerializer) | ||
from recipes.models import (AmountIngredient, Cart, Favorites, Ingredient, | ||
Recipe, Tag) | ||
from users.models import CustomUser, Subscriptions | ||
|
||
|
||
class CustomUserViewSet(UserViewSet): | ||
"""ViewSet для управления пользовательскими данными.""" | ||
|
||
permission_classes = [IsAuthenticatedOrReadOnly, ] | ||
pagination_class = CustomPaginator | ||
|
||
@action(detail=False, methods=['get'], | ||
permission_classes=(IsAuthenticated,)) | ||
def me(self, request): | ||
serializer = CustomUserSerializer(request.user, | ||
context={'request': request}) | ||
return Response(serializer.data, status=status.HTTP_200_OK) | ||
|
||
@action(detail=True, methods=['post'], | ||
permission_classes=[IsAuthenticated, ]) | ||
def subscribe(self, request, **kwargs): | ||
user = request.user | ||
author = get_object_or_404(CustomUser, pk=self.kwargs['id']) | ||
if user == author: | ||
return Response({'You can not subscribe yourself.'}, | ||
status=status.HTTP_400_BAD_REQUEST) | ||
if request.method == 'POST': | ||
subscription, created = Subscriptions.objects.get_or_create( | ||
user=user, author=author | ||
) | ||
if created: | ||
serializer = SubscriptionsSerializer( | ||
subscription, | ||
context={'request': request}, | ||
is_subscribed=True | ||
) | ||
return Response(serializer.data, | ||
status=status.HTTP_201_CREATED) | ||
else: | ||
return Response({'You are already subscribed this account.'}, | ||
status=status.HTTP_400_BAD_REQUEST) | ||
|
||
@subscribe.mapping.delete | ||
def unsubscribe(self, request, **kwargs): | ||
user = request.user | ||
author = get_object_or_404(CustomUser, pk=self.kwargs['id']) | ||
subscription = Subscriptions.objects.filter(user=user, | ||
author=author).first() | ||
if subscription: | ||
subscription.delete() | ||
return Response(status=status.HTTP_204_NO_CONTENT) | ||
else: | ||
return Response({'You are not subscribing this account.'}, | ||
status=status.HTTP_400_BAD_REQUEST) | ||
|
||
@action(detail=False, methods=['get'], | ||
permission_classes=(IsAuthenticated,)) | ||
def subscriptions(self, request): | ||
user = request.user | ||
queryset = Subscriptions.objects.filter(user=user) | ||
page = self.paginate_queryset(queryset) | ||
serializer = SubscriptionsSerializer(page, many=True, | ||
context={'request': request}) | ||
return self.get_paginated_response(serializer.data) | ||
|
||
|
||
class TagViewSet(viewsets.ReadOnlyModelViewSet): | ||
"""ViewSet для управления тегами.""" | ||
|
||
queryset = Tag.objects.all() | ||
serializer_class = TagSerializer | ||
permission_classes = [AdminOrReadOnly, ] | ||
|
||
|
||
class IngredientViewSet(viewsets.ReadOnlyModelViewSet): | ||
"""ViewSet для управления ингредиентами.""" | ||
|
||
queryset = Ingredient.objects.all() | ||
serializer_class = IngredientSerializer | ||
filter_backends = (filters.SearchFilter,) | ||
search_fields = ('^name',) | ||
|
||
def get_queryset(self): | ||
queryset = super().get_queryset() | ||
name = self.request.query_params.get('name') | ||
if name: | ||
queryset = queryset.filter(name__icontains=name) | ||
return queryset | ||
|
||
|
||
class RecipeViewSet(viewsets.ModelViewSet): | ||
"""ViewSet для управления рецептами.""" | ||
|
||
queryset = Recipe.objects.all() | ||
permission_classes = [AuthorAdminOrReadOnly, ] | ||
filter_backends = (DjangoFilterBackend,) | ||
filterset_class = RecipeFilter | ||
pagination_class = CustomPaginator | ||
|
||
def get_serializer_class(self): | ||
if self.action in ('list', 'retrieve'): | ||
return RecipeGetSerializer | ||
return RecipeCreateSerializer | ||
|
||
@action(detail=True, methods=['post'], | ||
permission_classes=[IsAuthenticated, ]) | ||
def favorite(self, request, pk=None): | ||
if request.method == 'POST': | ||
return self.add_to_list(request, pk, Favorites) | ||
elif request.method == 'DELETE': | ||
return self.remove_from_list(request, pk, Favorites) | ||
|
||
@action(detail=True, methods=['post'], | ||
permission_classes=[IsAuthenticated, ]) | ||
def shopping_cart(self, request, pk=None): | ||
if request.method == 'POST': | ||
return self.add_to_list(request, pk, Cart) | ||
elif request.method == 'DELETE': | ||
return self.remove_from_list(request, pk, Cart) | ||
|
||
def add_to_list(self, request, pk, model): | ||
try: | ||
recipe = Recipe.objects.get(id=pk) | ||
except Recipe.DoesNotExist: | ||
return Response({'There is no recipe like that.'}, | ||
status=status.HTTP_400_BAD_REQUEST) | ||
serializer = AddToRecipeSerializer(recipe) | ||
if model.objects.filter(user=request.user, recipe=recipe).exists(): | ||
return Response({'There is the recipe in list.'}, | ||
status=status.HTTP_400_BAD_REQUEST) | ||
model.objects.create(user=request.user, recipe=recipe) | ||
return Response(serializer.data, status=status.HTTP_201_CREATED) | ||
|
||
@favorite.mapping.delete | ||
@shopping_cart.mapping.delete | ||
def remove_from_list(self, request, pk=None, model=None): | ||
recipe = get_object_or_404(Recipe, id=pk) | ||
if not model.objects.filter(user=request.user, | ||
recipe=recipe).exists(): | ||
return Response({'There is no recipe in list.'}, | ||
status=status.HTTP_400_BAD_REQUEST) | ||
model.objects.filter(user=request.user, recipe=recipe).delete() | ||
return Response(status=status.HTTP_204_NO_CONTENT) | ||
|
||
def perform_create(self, serializer): | ||
if self.request.user.is_authenticated: | ||
serializer.save(author=self.request.user) | ||
else: | ||
raise AuthenticationFailed() | ||
|
||
@action(detail=False, methods=['get'], | ||
permission_classes=[IsAuthenticated]) | ||
def download_shopping_cart(self, request): | ||
final_list = {} | ||
ingredient = AmountIngredient.objects.filter( | ||
recipe__cart_recipe__user=request.user | ||
).values_list( | ||
'ingredient__name', 'ingredient__measurement_unit' | ||
).annotate(total_amount=Sum('amount')) | ||
for item in ingredient: | ||
if len(item) == 2: | ||
name, measurement_unit = item | ||
amount = 0 | ||
elif len(item) == 3: | ||
name, measurement_unit, amount = item | ||
else: | ||
continue | ||
final_list[name] = { | ||
'measurement_unit': measurement_unit, | ||
'amount': amount | ||
} | ||
response = HttpResponse(content_type='text/csv; charset=utf-8') | ||
response['Content-Disposition'] = 'attachment; ' | ||
'filename="shopping_cart.csv"' | ||
writer = csv.writer(response) | ||
writer.writerow(['Наименование ингредиента', 'Единица измерения', | ||
'Количество']) | ||
for ingredient, info in final_list.items(): | ||
writer.writerow([ingredient, info['measurement_unit'], | ||
info['amount']]) | ||
return response |
Binary file not shown.