gm-259, gm-260, gm-261

This commit is contained in:
Anatoly 2019-10-29 17:16:39 +03:00
parent 13eaa94261
commit 03c75efece
15 changed files with 160 additions and 62 deletions

View File

@ -241,6 +241,20 @@ class User(AbstractUser):
template_name=settings.CHANGE_EMAIL_TEMPLATE,
context=context)
@property
def favorite_establishment_ids(self):
"""Return establishment IDs that in favorites for current user."""
return self.favorites.by_content_type(app_label='establishment',
model='establishment')\
.values_list('object_id', flat=True)
@property
def favorite_recipe_ids(self):
"""Return recipe IDs that in favorites for current user."""
return self.favorites.by_content_type(app_label='recipe',
model='recipe')\
.values_list('object_id', flat=True)
class UserRole(ProjectBaseMixin):
"""UserRole model."""

View File

@ -248,14 +248,12 @@ class EstablishmentQuerySet(models.QuerySet):
def annotate_in_favorites(self, user):
"""Annotate flag in_favorites"""
favorite_establishments = []
favorite_establishment_ids = []
if user.is_authenticated:
favorite_establishments = user.favorites.by_content_type(app_label='establishment',
model='establishment') \
.values_list('object_id', flat=True)
favorite_establishment_ids = user.favorite_establishment_ids
return self.annotate(in_favorites=Case(
When(
id__in=favorite_establishments,
id__in=favorite_establishment_ids,
then=True),
default=False,
output_field=models.BooleanField(default=False)))

View File

@ -5,15 +5,14 @@ from rest_framework import serializers
from comment import models as comment_models
from comment.serializers import common as comment_serializers
from establishment import models
from favorites.models import Favorites
from location.serializers import AddressBaseSerializer
from main.serializers import AwardSerializer, CurrencySerializer
from review import models as review_models
from tag.serializers import TagBaseSerializer
from timetable.serialziers import ScheduleRUDSerializer
from utils import exceptions as utils_exceptions
from utils.serializers import ProjectModelSerializer
from utils.serializers import TranslatedField
from utils.serializers import (ProjectModelSerializer, TranslatedField,
FavoritesCreateSerializer)
class ContactPhonesSerializer(serializers.ModelSerializer):
@ -281,26 +280,13 @@ class EstablishmentCommentRUDSerializer(comment_serializers.CommentSerializer):
]
class EstablishmentFavoritesCreateSerializer(serializers.ModelSerializer):
"""Create comment serializer"""
class Meta:
"""Serializer for model Comment"""
model = Favorites
fields = [
'id',
'created',
]
def get_user(self):
"""Get user from request"""
return self.context.get('request').user
class EstablishmentFavoritesCreateSerializer(FavoritesCreateSerializer):
"""Serializer to favorite object w/ model Establishment."""
def validate(self, attrs):
"""Override validate method"""
"""Overridden validate method"""
# Check establishment object
establishment_slug = self.context.get('request').parser_context.get('kwargs').get('slug')
establishment_qs = models.Establishment.objects.filter(slug=establishment_slug)
establishment_qs = models.Establishment.objects.filter(slug=self.slug)
# Check establishment obj by slug from lookup_kwarg
if not establishment_qs.exists():
@ -309,18 +295,16 @@ class EstablishmentFavoritesCreateSerializer(serializers.ModelSerializer):
establishment = establishment_qs.first()
# Check existence in favorites
if self.get_user().favorites.by_content_type(app_label='establishment',
model='establishment')\
.by_object_id(object_id=establishment.id).exists():
if establishment.favorites.filter(user=self.user).exists():
raise utils_exceptions.FavoritesError()
attrs['establishment'] = establishment
return attrs
def create(self, validated_data, *args, **kwargs):
"""Override create method"""
"""Overridden create method"""
validated_data.update({
'user': self.get_user(),
'user': self.user,
'content_object': validated_data.pop('establishment')
})
return super().create(validated_data)

View File

@ -9,7 +9,6 @@ urlpatterns = [
path('', views.EstablishmentListView.as_view(), name='list'),
path('recent-reviews/', views.EstablishmentRecentReviewListView.as_view(),
name='recent-reviews'),
# path('wineries/', views.WineriesListView.as_view(), name='wineries-list'),
path('slug/<slug:slug>/', views.EstablishmentRetrieveView.as_view(), name='detail'),
path('slug/<slug:slug>/similar/', views.EstablishmentSimilarListView.as_view(), name='similar'),
path('slug/<slug:slug>/comments/', views.EstablishmentCommentListView.as_view(), name='list-comments'),
@ -18,5 +17,5 @@ urlpatterns = [
path('slug/<slug:slug>/comments/<int:comment_id>/', views.EstablishmentCommentRUDView.as_view(),
name='rud-comment'),
path('slug/<slug:slug>/favorites/', views.EstablishmentFavoritesCreateDestroyView.as_view(),
name='add-to-favorites')
name='create-destroy-favorites')
]

View File

@ -138,15 +138,12 @@ class EstablishmentFavoritesCreateDestroyView(generics.CreateAPIView, generics.D
"""
Returns the object the view is displaying.
"""
establishment_obj = get_object_or_404(models.Establishment,
slug=self.kwargs['slug'])
obj = get_object_or_404(
self.request.user.favorites.by_content_type(app_label='establishment',
model='establishment')
.by_object_id(object_id=establishment_obj.pk))
establishment = get_object_or_404(models.Establishment,
slug=self.kwargs['slug'])
favorites = get_object_or_404(establishment.favorites.filter(user=self.request.user))
# May raise a permission denied
self.check_object_permissions(self.request, obj)
return obj
self.check_object_permissions(self.request, favorites)
return favorites
class EstablishmentNearestRetrieveView(EstablishmentListView, generics.ListAPIView):
@ -170,14 +167,3 @@ class EstablishmentNearestRetrieveView(EstablishmentListView, generics.ListAPIVi
return qs.by_distance_from_point(**{k: v for k, v in filter_kwargs.items()
if v is not None})
return qs
# Wineries
# todo: find out about difference between subtypes data
# class WineriesListView(EstablishmentListView):
# """Return list establishments with type Wineries"""
#
# def get_queryset(self):
# """Overridden get_queryset method."""
# qs = super(WineriesListView, self).get_queryset()
# return qs.with_type_related().wineries()

View File

@ -8,4 +8,6 @@ app_name = 'favorites'
urlpatterns = [
path('establishments/', views.FavoritesEstablishmentListView.as_view(),
name='establishment-list'),
path('products/', views.FavoritesProductListView.as_view(),
name='product-list'),
]

View File

@ -3,6 +3,9 @@ from rest_framework import generics
from establishment.models import Establishment
from establishment.filters import EstablishmentFilter
from establishment.serializers import EstablishmentBaseSerializer
from product.models import Product
from product.serializers import ProductBaseSerializer
from product.filters import ProductFilterSet
from .models import Favorites
@ -15,7 +18,7 @@ class FavoritesBaseView(generics.GenericAPIView):
class FavoritesEstablishmentListView(generics.ListAPIView):
"""List views for favorites"""
"""List views for establishments in favorites."""
serializer_class = EstablishmentBaseSerializer
filter_class = EstablishmentFilter
@ -24,3 +27,15 @@ class FavoritesEstablishmentListView(generics.ListAPIView):
"""Override get_queryset method"""
return Establishment.objects.filter(favorites__user=self.request.user)\
.order_by('-favorites')
class FavoritesProductListView(generics.ListAPIView):
"""List views for products in favorites."""
serializer_class = ProductBaseSerializer
filter_class = ProductFilterSet
def get_queryset(self):
"""Override get_queryset method"""
return Product.objects.filter(favorites__user=self.request.user)\
.order_by('-favorites')

View File

@ -5,7 +5,7 @@ from django_filters import rest_framework as filters
from product import models
class ProductListFilterSet(filters.FilterSet):
class ProductFilterSet(filters.FilterSet):
"""Product filter set."""
establishment_id = filters.NumberFilter()

View File

@ -0,0 +1,18 @@
# Generated by Django 2.2.4 on 2019-10-29 14:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('product', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='product',
name='slug',
field=models.SlugField(max_length=255, null=True, unique=True, verbose_name='Establishment slug'),
),
]

View File

@ -1,5 +1,6 @@
"""Product app models."""
from django.db import models
from django.contrib.contenttypes import fields as generic
from django.core.exceptions import ValidationError
from django.contrib.postgres.fields import JSONField
from django.utils.translation import gettext_lazy as _
@ -141,6 +142,9 @@ class Product(TranslatedFieldsMixin, BaseAttributes):
wine_appellation = models.ForeignKey('location.WineAppellation', on_delete=models.PROTECT,
blank=True, null=True,
verbose_name=_('wine appellation'))
slug = models.SlugField(unique=True, max_length=255, null=True,
verbose_name=_('Establishment slug'))
favorites = generic.GenericRelation(to='favorites.Favorites')
objects = ProductManager.from_queryset(ProductQuerySet)()

View File

@ -1,9 +1,11 @@
"""Product app serializers."""
from rest_framework import serializers
from utils.serializers import TranslatedField
from utils.serializers import TranslatedField, FavoritesCreateSerializer
from product.models import Product, ProductSubType, ProductType
from utils import exceptions as utils_exceptions
from django.utils.translation import gettext_lazy as _
from location.serializers import (WineRegionBaseSerializer, WineAppellationBaseSerializer,
CountrySimpleSerializer)
CountrySimpleSerializer)
class ProductSubTypeBaseSerializer(serializers.ModelSerializer):
@ -50,6 +52,7 @@ class ProductBaseSerializer(serializers.ModelSerializer):
model = Product
fields = [
'id',
'slug',
'name_translated',
'category_display',
'description_translated',
@ -61,3 +64,33 @@ class ProductBaseSerializer(serializers.ModelSerializer):
'wine_appellation',
'available_countries',
]
class ProductFavoritesCreateSerializer(FavoritesCreateSerializer):
"""Serializer to create favorite object w/ model Product."""
def validate(self, attrs):
"""Overridden validate method"""
# Check establishment object
product_qs = Product.objects.filter(slug=self.slug)
# Check establishment obj by slug from lookup_kwarg
if not product_qs.exists():
raise serializers.ValidationError({'detail': _('Object not found.')})
else:
product = product_qs.first()
# Check existence in favorites
if product.favorites.filter(user=self.user).exists():
raise utils_exceptions.FavoritesError()
attrs['product'] = product
return attrs
def create(self, validated_data, *args, **kwargs):
"""Overridden create method"""
validated_data.update({
'user': self.user,
'content_object': validated_data.pop('product')
})
return super().create(validated_data)

View File

@ -6,5 +6,7 @@ from product import views
app_name = 'product'
urlpatterns = [
path('', views.ProductListView.as_view(), name='list')
path('', views.ProductListView.as_view(), name='list'),
path('slug/<slug:slug>/favorites/', views.CreateFavoriteProductView.as_view(),
name='create-destroy-favorites')
]

View File

@ -1,5 +1,6 @@
"""Product app views."""
from rest_framework import generics, permissions
from django.shortcuts import get_object_or_404
from product.models import Product
from product import serializers
from product import filters
@ -17,4 +18,22 @@ class ProductListView(ProductBaseView, generics.ListAPIView):
"""List view for model Product."""
permission_classes = (permissions.AllowAny, )
serializer_class = serializers.ProductBaseSerializer
filter_class = filters.ProductListFilterSet
filter_class = filters.ProductFilterSet
class CreateFavoriteProductView(generics.CreateAPIView,
generics.DestroyAPIView):
"""View for create/destroy product in favorites."""
serializer_class = serializers.ProductFavoritesCreateSerializer
lookup_field = 'slug'
def get_object(self):
"""
Returns the object the view is displaying.
"""
product = get_object_or_404(Product, slug=self.kwargs['slug'])
favorites = get_object_or_404(product.favorites.filter(user=self.request.user))
# May raise a permission denied
self.check_object_permissions(self.request, favorites)
return favorites

View File

@ -15,14 +15,12 @@ class RecipeQuerySet(models.QuerySet):
def annotate_in_favorites(self, user):
"""Annotate flag in_favorites"""
favorite_establishments = []
favorite_recipe_ids = []
if user.is_authenticated:
favorite_establishments = user.favorites.by_content_type(app_label='recipe',
model='recipe') \
.values_list('object_id', flat=True)
favorite_recipe_ids = user.favorite_recipe_ids
return self.annotate(in_favorites=models.Case(
models.When(
id__in=favorite_establishments,
id__in=favorite_recipe_ids,
then=True),
default=False,
output_field=models.BooleanField(default=False)))

View File

@ -4,6 +4,7 @@ from django.core import exceptions
from rest_framework import serializers
from utils import models
from translation.models import Language
from favorites.models import Favorites
class EmptySerializer(serializers.Serializer):
@ -72,3 +73,28 @@ class ProjectModelSerializer(serializers.ModelSerializer):
"""Overrided ModelSerializer."""
serializers.ModelSerializer.serializer_field_mapping[models.TJSONField] = TJSONField
class FavoritesCreateSerializer(serializers.ModelSerializer):
"""Serializer to favorite object."""
class Meta:
"""Serializer for model Comment."""
model = Favorites
fields = [
'id',
'created',
]
@property
def request(self):
return self.context.get('request')
@property
def user(self):
"""Get user from request"""
return self.request.user
@property
def slug(self):
return self.request.parser_context.get('kwargs').get('slug')