create, delete, get favorite news

This commit is contained in:
alex 2019-11-05 17:52:36 +03:00
parent 28471686be
commit d853960d2e
7 changed files with 93 additions and 14 deletions

View File

@ -10,4 +10,6 @@ urlpatterns = [
name='establishment-list'), name='establishment-list'),
path('products/', views.FavoritesProductListView.as_view(), path('products/', views.FavoritesProductListView.as_view(),
name='product-list'), name='product-list'),
path('news/', views.FavoritesNewsListView.as_view(),
name='news-list'),
] ]

View File

@ -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 news.filters import NewsListFilterSet
from news.models import News
from news.serializers import NewsBaseSerializer
from product.models import Product from product.models import Product
from product.serializers import ProductBaseSerializer from product.serializers import ProductBaseSerializer
from product.filters import ProductFilterSet from product.filters import ProductFilterSet
@ -25,8 +28,8 @@ class FavoritesEstablishmentListView(generics.ListAPIView):
def get_queryset(self): def get_queryset(self):
"""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): class FavoritesProductListView(generics.ListAPIView):
@ -37,5 +40,16 @@ class FavoritesProductListView(generics.ListAPIView):
def get_queryset(self): def get_queryset(self):
"""Override get_queryset method""" """Override get_queryset method"""
return Product.objects.filter(favorites__user=self.request.user)\ return Product.objects.filter(favorites__user=self.request.user) \
.order_by('-favorites') .order_by('-favorites')
class FavoritesNewsListView(generics.ListAPIView):
"""List views for news in favorites."""
serializer_class = NewsBaseSerializer
filter_class = NewsListFilterSet
def get_queryset(self):
"""Override get_queryset method"""
return News.objects.filter(favorites__user=self.request.user).order_by('-favorites')

View File

@ -159,7 +159,7 @@ class News(BaseAttributes, TranslatedFieldsMixin):
verbose_name=_('Tags')) verbose_name=_('Tags'))
gallery = models.ManyToManyField('gallery.Image', through='news.NewsGallery') gallery = models.ManyToManyField('gallery.Image', through='news.NewsGallery')
ratings = generic.GenericRelation(Rating) ratings = generic.GenericRelation(Rating)
favorites = generic.GenericRelation(to='favorites.Favorites')
agenda = models.ForeignKey('news.Agenda', blank=True, null=True, agenda = models.ForeignKey('news.Agenda', blank=True, null=True,
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
verbose_name=_('agenda')) verbose_name=_('agenda'))

View File

@ -8,7 +8,8 @@ from location import models as location_models
from location.serializers import CountrySimpleSerializer, AddressBaseSerializer from location.serializers import CountrySimpleSerializer, AddressBaseSerializer
from news import models from news import models
from tag.serializers import TagBaseSerializer from tag.serializers import TagBaseSerializer
from utils.serializers import TranslatedField, ProjectModelSerializer from utils import exceptions as utils_exceptions
from utils.serializers import TranslatedField, ProjectModelSerializer, FavoritesCreateSerializer
class AgendaSerializer(ProjectModelSerializer): class AgendaSerializer(ProjectModelSerializer):
@ -293,3 +294,33 @@ class NewsBackOfficeGallerySerializer(serializers.ModelSerializer):
attrs['image'] = image attrs['image'] = image
return attrs return attrs
class NewsFavoritesCreateSerializer(FavoritesCreateSerializer):
"""Serializer to favorite object w/ model News."""
def validate(self, attrs):
"""Overridden validate method"""
# Check establishment object
news_qs = models.News.objects.filter(slug=self.slug)
# Check establishment obj by slug from lookup_kwarg
if not news_qs.exists():
raise serializers.ValidationError({'detail': _('Object not found.')})
else:
news = news_qs.first()
# Check existence in favorites
if news.favorites.filter(user=self.user).exists():
raise utils_exceptions.FavoritesError()
attrs['news'] = news
return attrs
def create(self, validated_data, *args, **kwargs):
"""Overridden create method"""
validated_data.update({
'user': self.user,
'content_object': validated_data.pop('news')
})
return super().create(validated_data)

View File

@ -9,6 +9,8 @@ from news.models import NewsType, News
from account.models import User, Role, UserRole from account.models import User, Role, UserRole
from translation.models import Language from translation.models import Language
from location.models import Country from location.models import Country
# Create your tests here. # Create your tests here.
@ -67,7 +69,7 @@ class NewsTestCase(BaseTestCase):
super().setUp() super().setUp()
def test_news_post(self): def test_news_post(self):
test_news ={ test_news = {
"title": {"en-GB": "Test news POST"}, "title": {"en-GB": "Test news POST"},
"news_type_id": self.test_news_type.id, "news_type_id": self.test_news_type.id,
"description": {"en-GB": "Description test news"}, "description": {"en-GB": "Description test news"},
@ -108,9 +110,21 @@ class NewsTestCase(BaseTestCase):
'description': {"en-GB": "Description test news!"}, 'description': {"en-GB": "Description test news!"},
'slug': self.test_news.slug, 'slug': self.test_news.slug,
'start': self.test_news.start, 'start': self.test_news.start,
'news_type_id':self.test_news.news_type_id, 'news_type_id': self.test_news.news_type_id,
'country_id': self.country_ru.id 'country_id': self.country_ru.id
} }
response = self.client.put(url, data=data, format='json') response = self.client.put(url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_web_favorite_create_delete(self):
data = {
"user": self.user.id,
"object_id": self.test_news.id
}
response = self.client.post(f'/api/web/news/slug/{self.test_news.slug}/favorites/', data=data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
response = self.client.delete(f'/api/web/news/slug/{self.test_news.slug}/favorites/', format='json')
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

View File

@ -8,4 +8,5 @@ urlpatterns = [
path('', views.NewsListView.as_view(), name='list'), path('', views.NewsListView.as_view(), name='list'),
path('types/', views.NewsTypeListView.as_view(), name='type'), path('types/', views.NewsTypeListView.as_view(), name='type'),
path('slug/<slug:slug>/', views.NewsDetailView.as_view(), name='rud'), path('slug/<slug:slug>/', views.NewsDetailView.as_view(), name='rud'),
path('slug/<slug:slug>/favorites/', views.NewsFavoritesCreateDestroyView.as_view(), name='create-destroy-favorites')
] ]

View File

@ -20,8 +20,8 @@ class NewsMixinView:
def get_queryset(self, *args, **kwargs): def get_queryset(self, *args, **kwargs):
"""Override get_queryset method.""" """Override get_queryset method."""
qs = models.News.objects.published() \ qs = models.News.objects.published() \
.with_base_related() \ .with_base_related() \
.order_by('-is_highlighted', '-created') .order_by('-is_highlighted', '-created')
country_code = self.request.country_code country_code = self.request.country_code
if country_code: if country_code:
qs = qs.by_country_code(country_code) qs = qs.by_country_code(country_code)
@ -51,7 +51,7 @@ class NewsTypeListView(generics.ListAPIView):
"""NewsType list view.""" """NewsType list view."""
pagination_class = None pagination_class = None
permission_classes = (permissions.AllowAny, ) permission_classes = (permissions.AllowAny,)
queryset = models.NewsType.objects.all() queryset = models.NewsType.objects.all()
serializer_class = serializers.NewsTypeSerializer serializer_class = serializers.NewsTypeSerializer
@ -70,7 +70,7 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView,
serializer_class = serializers.NewsBackOfficeBaseSerializer serializer_class = serializers.NewsBackOfficeBaseSerializer
create_serializers_class = serializers.NewsBackOfficeDetailSerializer create_serializers_class = serializers.NewsBackOfficeDetailSerializer
permission_classes = [IsCountryAdmin|IsContentPageManager] permission_classes = [IsCountryAdmin | IsContentPageManager]
def get_serializer_class(self): def get_serializer_class(self):
"""Override serializer class.""" """Override serializer class."""
@ -146,9 +146,26 @@ class NewsBackOfficeRUDView(NewsBackOfficeMixinView,
"""Resource for detailed information about news for back-office users.""" """Resource for detailed information about news for back-office users."""
serializer_class = serializers.NewsBackOfficeDetailSerializer serializer_class = serializers.NewsBackOfficeDetailSerializer
permission_classes = [IsCountryAdmin|IsContentPageManager] permission_classes = [IsCountryAdmin | IsContentPageManager]
def get(self, request, pk, *args, **kwargs): def get(self, request, pk, *args, **kwargs):
add_rating(remote_addr=request.META.get('REMOTE_ADDR'), add_rating(remote_addr=request.META.get('REMOTE_ADDR'),
pk=pk, model='news', app_label='news') pk=pk, model='news', app_label='news')
return self.retrieve(request, *args, **kwargs) return self.retrieve(request, *args, **kwargs)
class NewsFavoritesCreateDestroyView(generics.CreateAPIView, generics.DestroyAPIView):
"""View for create/destroy news from favorites."""
serializer_class = serializers.NewsFavoritesCreateSerializer
lookup_field = 'slug'
def get_object(self):
"""
Returns the object the view is displaying.
"""
news = get_object_or_404(models.News, slug=self.kwargs['slug'])
favorites = get_object_or_404(news.favorites.filter(user=self.request.user))
# May raise a permission denied
self.check_object_permissions(self.request, favorites)
return favorites