gault-millau/apps/news/views.py
Александр Пархомин af19896f41 add docstring for NewsBackOfficeLCView
2020-02-10 10:15:11 +03:00

318 lines
9.9 KiB
Python

"""News app views."""
from django.conf import settings
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.utils import translation
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import generics, permissions, response
from rest_framework.filters import OrderingFilter
from news import filters, models, serializers
from rating.tasks import add_rating
from utils.methods import get_permission_classes
from utils.permissions import IsContentPageManager
from utils.serializers import ImageBaseSerializer
from utils.views import CreateDestroyGalleryViewMixin, FavoritesCreateDestroyMixinView, \
CarouselCreateDestroyMixinView
class NewsMixinView:
"""News mixin."""
permission_classes = (permissions.AllowAny,)
serializer_class = serializers.NewsBaseSerializer
def get_queryset(self, *args, **kwargs):
"""Override get_queryset method."""
qs = models.News.objects.published() \
.with_base_related() \
.annotate_in_favorites(self.request.user) \
.order_by('-is_highlighted', '-publication_date', '-publication_time')
country_code = self.request.country_code
if country_code:
if kwargs.get('international_preferred') and country_code in settings.INTERNATIONAL_COUNTRY_CODES:
qs = qs.international_news()
else:
qs = qs.by_country_code(country_code)
# locale = kwargs.get('locale')
# if locale:
# qs = qs.by_locale(locale)
return qs
def get_object(self):
instance = self.get_queryset().with_base_related().filter(
slugs__values__contains=[self.kwargs['slug']]
).first()
if instance is None:
raise Http404
return instance
class NewsStatesView(generics.ListAPIView):
"""Possible project news states"""
pagination_class = None
serializer_class = serializers.NewsStatesSerializer
def get_queryset(self):
return None
def list(self, request, *args, **kwargs):
mutated_for_serializer = [{
'value': state[0],
'state_translated': state[1],
} for state in models.News.STATE_CHOICES]
serializer = self.get_serializer(mutated_for_serializer, many=True)
return response.Response(serializer.data)
class NewsListView(NewsMixinView, generics.ListAPIView):
"""News list view."""
serializer_class = serializers.NewsListSerializer
filter_class = filters.NewsListFilterSet
def get_queryset(self, *args, **kwargs):
locale = translation.get_language()
kwargs.update({
'international_preferred': True,
'locale': locale,
})
return super().get_queryset(*args, **kwargs)\
.filter(locale_to_description_is_active__values__contains=['True'])
class NewsDetailView(NewsMixinView, generics.RetrieveAPIView):
"""News detail view."""
lookup_field = None
serializer_class = serializers.NewsDetailWebSerializer
def get_queryset(self):
"""Override get_queryset method."""
qs = models.News.objects.all().annotate_in_favorites(self.request.user)
return qs
class NewsPreviewView(NewsMixinView, generics.RetrieveAPIView):
"""News preview view."""
lookup_field = None
serializer_class = serializers.NewsPreviewWebSerializer
def get_queryset(self):
"""Override get_queryset method."""
qs = models.News.objects.all().annotate_in_favorites(self.request.user)
return qs
class NewsTypeListView(generics.ListAPIView):
"""NewsType list view."""
pagination_class = None
permission_classes = (permissions.AllowAny,)
serializer_class = serializers.NewsTypeSerializer
def get_queryset(self):
"""Override get_queryset method."""
return models.NewsType.objects.with_base_related()
class NewsBackOfficeMixinView:
"""News back office mixin view."""
permission_classes = get_permission_classes(IsContentPageManager, IsContentPageManager)
def get_queryset(self):
"""Overridden get_queryset method."""
queryset = models.News.objects
if hasattr(self, 'request') and \
(hasattr(self.request, 'user') and hasattr(self.request, 'country_code')):
user = self.request.user
return (
queryset.with_base_related()
.annotate_in_favorites(user)
.available_news(user, self.request.country_code)
.order_by('-is_highlighted', '-created')
)
return queryset.none()
class NewsBackOfficeLCView(NewsBackOfficeMixinView,
generics.ListCreateAPIView):
"""
Resource for a list/create of news for back-office users.
**GET**
```
Implement getting list of news for back-office users.
```
**POST**
```
Implement create of news for back-office users.
```
"""
serializer_class = serializers.NewsBackOfficeBaseSerializer
filter_class = filters.NewsListFilterSet
create_serializers_class = serializers.NewsBackOfficeDetailSerializer
filter_backends = (OrderingFilter, DjangoFilterBackend)
ordering_fields = '__all__'
def get_serializer_class(self):
"""Override serializer class."""
if self.request.method == 'POST':
return self.create_serializers_class
return super().get_serializer_class()
def get_queryset(self):
"""Override get_queryset method."""
qs = super().get_queryset().with_extended_related()
if 'ordering' in self.request.query_params:
self.request.GET._mutable = True
if '-publication_datetime' in self.request.query_params['ordering']:
self.request.query_params['ordering'] = self.request.query_params['ordering']\
.replace('-publication_datetime', '-publication_date,-publication_time')
elif 'publication_datetime' in self.request.query_params['ordering']:
self.request.query_params['ordering'] = self.request.query_params['ordering']\
.replace('publication_datetime', 'publication_date,publication_time')
self.request.GET._mutable = False
return qs
class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView,
CreateDestroyGalleryViewMixin):
"""
## News gallery image Create/Destroy view
### *POST*
#### Description
Attaching existing **image** by `image identifier` to **news** by `news identifier`
in request kwargs.
##### Request
```
No body
```
##### Response
E.g.:
```
No content
```
### *DELETE*
#### Description
Delete existing **gallery image** from **news** gallery, by `image identifier`
and `news identifier` in request kwargs.
**Note**:
> Image wouldn't be deleted after all.
##### Request
```
No body
```
##### Response
```
No content
```
"""
serializer_class = serializers.NewsBackOfficeGallerySerializer
def create(self, request, *args, **kwargs):
_ = super().create(request, *args, **kwargs)
news_qs = self.filter_queryset(self.get_queryset())
return response.Response(
data=serializers.NewsBackOfficeDetailSerializer(get_object_or_404(news_qs, pk=kwargs.get('pk'))).data
)
def get_object(self):
"""
Returns the object the view is displaying.
"""
news_qs = self.filter_queryset(self.get_queryset())
news = get_object_or_404(news_qs, pk=self.kwargs.get('pk'))
gallery = get_object_or_404(news.news_gallery, image_id=self.kwargs.get('image_id'))
# May raise a permission denied
self.check_object_permissions(self.request, gallery)
return gallery
class NewsBackOfficeGalleryListView(NewsBackOfficeMixinView,
generics.ListAPIView):
"""
## News gallery image list view
### *GET*
#### Description
Returning paginated list of news images by `news identifier`,
with cropped images.
##### Response
E.g.:
```
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 11,
...
}
]
}
```
"""
serializer_class = ImageBaseSerializer
def get_object(self):
"""Override get_object method."""
qs = super(NewsBackOfficeGalleryListView, self).get_queryset()
news = get_object_or_404(qs, pk=self.kwargs.get('pk'))
# May raise a permission denied
self.check_object_permissions(self.request, news)
return news
def get_queryset(self):
"""Override get_queryset method."""
return self.get_object().crop_gallery
class NewsBackOfficeRUDView(NewsBackOfficeMixinView,
generics.RetrieveUpdateDestroyAPIView):
"""Resource for detailed information about news for back-office users."""
serializer_class = serializers.NewsBackOfficeDetailSerializer
def get(self, request, pk, *args, **kwargs):
add_rating(remote_addr=request.META.get('REMOTE_ADDR'),
pk=pk, model='news', app_label='news')
return self.retrieve(request, *args, **kwargs)
class NewsFavoritesCreateDestroyView(FavoritesCreateDestroyMixinView):
"""View for create/destroy news from favorites."""
_model = models.News
serializer_class = serializers.NewsFavoritesCreateSerializer
class NewsCarouselCreateDestroyView(CarouselCreateDestroyMixinView):
"""View for create/destroy news from carousel."""
_model = models.News
serializer_class = serializers.NewsCarouselCreateSerializer
class NewsCloneView(generics.CreateAPIView):
"""View for creating clone News"""
permission_classes = (permissions.AllowAny,)
serializer_class = serializers.NewsCloneCreateSerializer
queryset = models.News.objects.all()