gm-259, gm-260, gm-261
This commit is contained in:
parent
13eaa94261
commit
03c75efece
|
|
@ -241,6 +241,20 @@ class User(AbstractUser):
|
||||||
template_name=settings.CHANGE_EMAIL_TEMPLATE,
|
template_name=settings.CHANGE_EMAIL_TEMPLATE,
|
||||||
context=context)
|
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):
|
class UserRole(ProjectBaseMixin):
|
||||||
"""UserRole model."""
|
"""UserRole model."""
|
||||||
|
|
|
||||||
|
|
@ -248,14 +248,12 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
|
|
||||||
def annotate_in_favorites(self, user):
|
def annotate_in_favorites(self, user):
|
||||||
"""Annotate flag in_favorites"""
|
"""Annotate flag in_favorites"""
|
||||||
favorite_establishments = []
|
favorite_establishment_ids = []
|
||||||
if user.is_authenticated:
|
if user.is_authenticated:
|
||||||
favorite_establishments = user.favorites.by_content_type(app_label='establishment',
|
favorite_establishment_ids = user.favorite_establishment_ids
|
||||||
model='establishment') \
|
|
||||||
.values_list('object_id', flat=True)
|
|
||||||
return self.annotate(in_favorites=Case(
|
return self.annotate(in_favorites=Case(
|
||||||
When(
|
When(
|
||||||
id__in=favorite_establishments,
|
id__in=favorite_establishment_ids,
|
||||||
then=True),
|
then=True),
|
||||||
default=False,
|
default=False,
|
||||||
output_field=models.BooleanField(default=False)))
|
output_field=models.BooleanField(default=False)))
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,14 @@ from rest_framework import serializers
|
||||||
from comment import models as comment_models
|
from comment import models as comment_models
|
||||||
from comment.serializers import common as comment_serializers
|
from comment.serializers import common as comment_serializers
|
||||||
from establishment import models
|
from establishment import models
|
||||||
from favorites.models import Favorites
|
|
||||||
from location.serializers import AddressBaseSerializer
|
from location.serializers import AddressBaseSerializer
|
||||||
from main.serializers import AwardSerializer, CurrencySerializer
|
from main.serializers import AwardSerializer, CurrencySerializer
|
||||||
from review import models as review_models
|
from review import models as review_models
|
||||||
from tag.serializers import TagBaseSerializer
|
from tag.serializers import TagBaseSerializer
|
||||||
from timetable.serialziers import ScheduleRUDSerializer
|
from timetable.serialziers import ScheduleRUDSerializer
|
||||||
from utils import exceptions as utils_exceptions
|
from utils import exceptions as utils_exceptions
|
||||||
from utils.serializers import ProjectModelSerializer
|
from utils.serializers import (ProjectModelSerializer, TranslatedField,
|
||||||
from utils.serializers import TranslatedField
|
FavoritesCreateSerializer)
|
||||||
|
|
||||||
|
|
||||||
class ContactPhonesSerializer(serializers.ModelSerializer):
|
class ContactPhonesSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -281,26 +280,13 @@ class EstablishmentCommentRUDSerializer(comment_serializers.CommentSerializer):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentFavoritesCreateSerializer(serializers.ModelSerializer):
|
class EstablishmentFavoritesCreateSerializer(FavoritesCreateSerializer):
|
||||||
"""Create comment serializer"""
|
"""Serializer to favorite object w/ model Establishment."""
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
"""Override validate method"""
|
"""Overridden validate method"""
|
||||||
# Check establishment object
|
# Check establishment object
|
||||||
establishment_slug = self.context.get('request').parser_context.get('kwargs').get('slug')
|
establishment_qs = models.Establishment.objects.filter(slug=self.slug)
|
||||||
establishment_qs = models.Establishment.objects.filter(slug=establishment_slug)
|
|
||||||
|
|
||||||
# Check establishment obj by slug from lookup_kwarg
|
# Check establishment obj by slug from lookup_kwarg
|
||||||
if not establishment_qs.exists():
|
if not establishment_qs.exists():
|
||||||
|
|
@ -309,18 +295,16 @@ class EstablishmentFavoritesCreateSerializer(serializers.ModelSerializer):
|
||||||
establishment = establishment_qs.first()
|
establishment = establishment_qs.first()
|
||||||
|
|
||||||
# Check existence in favorites
|
# Check existence in favorites
|
||||||
if self.get_user().favorites.by_content_type(app_label='establishment',
|
if establishment.favorites.filter(user=self.user).exists():
|
||||||
model='establishment')\
|
|
||||||
.by_object_id(object_id=establishment.id).exists():
|
|
||||||
raise utils_exceptions.FavoritesError()
|
raise utils_exceptions.FavoritesError()
|
||||||
|
|
||||||
attrs['establishment'] = establishment
|
attrs['establishment'] = establishment
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
def create(self, validated_data, *args, **kwargs):
|
def create(self, validated_data, *args, **kwargs):
|
||||||
"""Override create method"""
|
"""Overridden create method"""
|
||||||
validated_data.update({
|
validated_data.update({
|
||||||
'user': self.get_user(),
|
'user': self.user,
|
||||||
'content_object': validated_data.pop('establishment')
|
'content_object': validated_data.pop('establishment')
|
||||||
})
|
})
|
||||||
return super().create(validated_data)
|
return super().create(validated_data)
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ urlpatterns = [
|
||||||
path('', views.EstablishmentListView.as_view(), name='list'),
|
path('', views.EstablishmentListView.as_view(), name='list'),
|
||||||
path('recent-reviews/', views.EstablishmentRecentReviewListView.as_view(),
|
path('recent-reviews/', views.EstablishmentRecentReviewListView.as_view(),
|
||||||
name='recent-reviews'),
|
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>/', views.EstablishmentRetrieveView.as_view(), name='detail'),
|
||||||
path('slug/<slug:slug>/similar/', views.EstablishmentSimilarListView.as_view(), name='similar'),
|
path('slug/<slug:slug>/similar/', views.EstablishmentSimilarListView.as_view(), name='similar'),
|
||||||
path('slug/<slug:slug>/comments/', views.EstablishmentCommentListView.as_view(), name='list-comments'),
|
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(),
|
path('slug/<slug:slug>/comments/<int:comment_id>/', views.EstablishmentCommentRUDView.as_view(),
|
||||||
name='rud-comment'),
|
name='rud-comment'),
|
||||||
path('slug/<slug:slug>/favorites/', views.EstablishmentFavoritesCreateDestroyView.as_view(),
|
path('slug/<slug:slug>/favorites/', views.EstablishmentFavoritesCreateDestroyView.as_view(),
|
||||||
name='add-to-favorites')
|
name='create-destroy-favorites')
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -138,15 +138,12 @@ class EstablishmentFavoritesCreateDestroyView(generics.CreateAPIView, generics.D
|
||||||
"""
|
"""
|
||||||
Returns the object the view is displaying.
|
Returns the object the view is displaying.
|
||||||
"""
|
"""
|
||||||
establishment_obj = get_object_or_404(models.Establishment,
|
establishment = get_object_or_404(models.Establishment,
|
||||||
slug=self.kwargs['slug'])
|
slug=self.kwargs['slug'])
|
||||||
obj = get_object_or_404(
|
favorites = get_object_or_404(establishment.favorites.filter(user=self.request.user))
|
||||||
self.request.user.favorites.by_content_type(app_label='establishment',
|
|
||||||
model='establishment')
|
|
||||||
.by_object_id(object_id=establishment_obj.pk))
|
|
||||||
# May raise a permission denied
|
# May raise a permission denied
|
||||||
self.check_object_permissions(self.request, obj)
|
self.check_object_permissions(self.request, favorites)
|
||||||
return obj
|
return favorites
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentNearestRetrieveView(EstablishmentListView, generics.ListAPIView):
|
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()
|
return qs.by_distance_from_point(**{k: v for k, v in filter_kwargs.items()
|
||||||
if v is not None})
|
if v is not None})
|
||||||
return qs
|
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()
|
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,6 @@ app_name = 'favorites'
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('establishments/', views.FavoritesEstablishmentListView.as_view(),
|
path('establishments/', views.FavoritesEstablishmentListView.as_view(),
|
||||||
name='establishment-list'),
|
name='establishment-list'),
|
||||||
|
path('products/', views.FavoritesProductListView.as_view(),
|
||||||
|
name='product-list'),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ from rest_framework import generics
|
||||||
from establishment.models import Establishment
|
from establishment.models import Establishment
|
||||||
from establishment.filters import EstablishmentFilter
|
from establishment.filters import EstablishmentFilter
|
||||||
from establishment.serializers import EstablishmentBaseSerializer
|
from establishment.serializers import EstablishmentBaseSerializer
|
||||||
|
from product.models import Product
|
||||||
|
from product.serializers import ProductBaseSerializer
|
||||||
|
from product.filters import ProductFilterSet
|
||||||
from .models import Favorites
|
from .models import Favorites
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -15,7 +18,7 @@ class FavoritesBaseView(generics.GenericAPIView):
|
||||||
|
|
||||||
|
|
||||||
class FavoritesEstablishmentListView(generics.ListAPIView):
|
class FavoritesEstablishmentListView(generics.ListAPIView):
|
||||||
"""List views for favorites"""
|
"""List views for establishments in favorites."""
|
||||||
|
|
||||||
serializer_class = EstablishmentBaseSerializer
|
serializer_class = EstablishmentBaseSerializer
|
||||||
filter_class = EstablishmentFilter
|
filter_class = EstablishmentFilter
|
||||||
|
|
@ -24,3 +27,15 @@ class FavoritesEstablishmentListView(generics.ListAPIView):
|
||||||
"""Override get_queryset method"""
|
"""Override get_queryset method"""
|
||||||
return Establishment.objects.filter(favorites__user=self.request.user)\
|
return Establishment.objects.filter(favorites__user=self.request.user)\
|
||||||
.order_by('-favorites')
|
.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')
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from django_filters import rest_framework as filters
|
||||||
from product import models
|
from product import models
|
||||||
|
|
||||||
|
|
||||||
class ProductListFilterSet(filters.FilterSet):
|
class ProductFilterSet(filters.FilterSet):
|
||||||
"""Product filter set."""
|
"""Product filter set."""
|
||||||
|
|
||||||
establishment_id = filters.NumberFilter()
|
establishment_id = filters.NumberFilter()
|
||||||
|
|
|
||||||
18
apps/product/migrations/0002_product_slug.py
Normal file
18
apps/product/migrations/0002_product_slug.py
Normal 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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
"""Product app models."""
|
"""Product app models."""
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.contrib.contenttypes import fields as generic
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.contrib.postgres.fields import JSONField
|
from django.contrib.postgres.fields import JSONField
|
||||||
from django.utils.translation import gettext_lazy as _
|
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,
|
wine_appellation = models.ForeignKey('location.WineAppellation', on_delete=models.PROTECT,
|
||||||
blank=True, null=True,
|
blank=True, null=True,
|
||||||
verbose_name=_('wine appellation'))
|
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)()
|
objects = ProductManager.from_queryset(ProductQuerySet)()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
"""Product app serializers."""
|
"""Product app serializers."""
|
||||||
from rest_framework import 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 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,
|
from location.serializers import (WineRegionBaseSerializer, WineAppellationBaseSerializer,
|
||||||
CountrySimpleSerializer)
|
CountrySimpleSerializer)
|
||||||
|
|
||||||
|
|
||||||
class ProductSubTypeBaseSerializer(serializers.ModelSerializer):
|
class ProductSubTypeBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -50,6 +52,7 @@ class ProductBaseSerializer(serializers.ModelSerializer):
|
||||||
model = Product
|
model = Product
|
||||||
fields = [
|
fields = [
|
||||||
'id',
|
'id',
|
||||||
|
'slug',
|
||||||
'name_translated',
|
'name_translated',
|
||||||
'category_display',
|
'category_display',
|
||||||
'description_translated',
|
'description_translated',
|
||||||
|
|
@ -61,3 +64,33 @@ class ProductBaseSerializer(serializers.ModelSerializer):
|
||||||
'wine_appellation',
|
'wine_appellation',
|
||||||
'available_countries',
|
'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)
|
||||||
|
|
@ -6,5 +6,7 @@ from product import views
|
||||||
app_name = 'product'
|
app_name = 'product'
|
||||||
|
|
||||||
urlpatterns = [
|
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')
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
"""Product app views."""
|
"""Product app views."""
|
||||||
from rest_framework import generics, permissions
|
from rest_framework import generics, permissions
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
from product.models import Product
|
from product.models import Product
|
||||||
from product import serializers
|
from product import serializers
|
||||||
from product import filters
|
from product import filters
|
||||||
|
|
@ -17,4 +18,22 @@ class ProductListView(ProductBaseView, generics.ListAPIView):
|
||||||
"""List view for model Product."""
|
"""List view for model Product."""
|
||||||
permission_classes = (permissions.AllowAny, )
|
permission_classes = (permissions.AllowAny, )
|
||||||
serializer_class = serializers.ProductBaseSerializer
|
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
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,12 @@ class RecipeQuerySet(models.QuerySet):
|
||||||
|
|
||||||
def annotate_in_favorites(self, user):
|
def annotate_in_favorites(self, user):
|
||||||
"""Annotate flag in_favorites"""
|
"""Annotate flag in_favorites"""
|
||||||
favorite_establishments = []
|
favorite_recipe_ids = []
|
||||||
if user.is_authenticated:
|
if user.is_authenticated:
|
||||||
favorite_establishments = user.favorites.by_content_type(app_label='recipe',
|
favorite_recipe_ids = user.favorite_recipe_ids
|
||||||
model='recipe') \
|
|
||||||
.values_list('object_id', flat=True)
|
|
||||||
return self.annotate(in_favorites=models.Case(
|
return self.annotate(in_favorites=models.Case(
|
||||||
models.When(
|
models.When(
|
||||||
id__in=favorite_establishments,
|
id__in=favorite_recipe_ids,
|
||||||
then=True),
|
then=True),
|
||||||
default=False,
|
default=False,
|
||||||
output_field=models.BooleanField(default=False)))
|
output_field=models.BooleanField(default=False)))
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ from django.core import exceptions
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from utils import models
|
from utils import models
|
||||||
from translation.models import Language
|
from translation.models import Language
|
||||||
|
from favorites.models import Favorites
|
||||||
|
|
||||||
|
|
||||||
class EmptySerializer(serializers.Serializer):
|
class EmptySerializer(serializers.Serializer):
|
||||||
|
|
@ -72,3 +73,28 @@ class ProjectModelSerializer(serializers.ModelSerializer):
|
||||||
"""Overrided ModelSerializer."""
|
"""Overrided ModelSerializer."""
|
||||||
|
|
||||||
serializers.ModelSerializer.serializer_field_mapping[models.TJSONField] = TJSONField
|
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')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user