Merge branch 'develop' of ssh://gl.id-east.ru:222/gm/gm-backend into develop

This commit is contained in:
Dmitriy Kuzmenko 2019-09-27 17:44:19 +03:00
commit 2af401daa5
9 changed files with 127 additions and 7 deletions

View File

@ -8,6 +8,8 @@ from django.utils.translation import gettext_lazy as _
from utils.models import ProjectBaseMixin, URLImageMixin from utils.models import ProjectBaseMixin, URLImageMixin
from utils.models import TranslatedFieldsMixin from utils.models import TranslatedFieldsMixin
from utils.querysets import RelatedObjectsCountMixin
# Mixins # Mixins
class CollectionNameMixin(models.Model): class CollectionNameMixin(models.Model):
@ -30,7 +32,7 @@ class CollectionDateMixin(models.Model):
# Models # Models
class CollectionQuerySet(models.QuerySet): class CollectionQuerySet(RelatedObjectsCountMixin):
"""QuerySet for model Collection""" """QuerySet for model Collection"""
def by_country_code(self, code): def by_country_code(self, code):

View File

@ -8,6 +8,7 @@ from http.cookies import SimpleCookie
from collection.models import Collection, Guide from collection.models import Collection, Guide
from location.models import Country from location.models import Country
from establishment.models import Establishment, EstablishmentType
# Create your tests here. # Create your tests here.
@ -81,3 +82,27 @@ class CollectionGuideDetailTests(CollectionDetailTests):
def test_guide_detail_Read(self): def test_guide_detail_Read(self):
response = self.client.get(f'/api/web/collections/guides/{self.guide.id}/', format='json') response = self.client.get(f'/api/web/collections/guides/{self.guide.id}/', format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
class CollectionWebHomeTests(CollectionDetailTests):
def setUp(self):
super().setUp()
self.establishment_type = EstablishmentType.objects.create(name="Test establishment type")
for i in range(1, 5):
setattr(self, f"establishment{i}",
Establishment.objects.create(
name=f"Test establishment {i}",
establishment_type_id=self.establishment_type.id,
is_publish=True,
slug=f"test-establishment-{i}"
)
)
getattr(self, f"establishment{i}").collections.add(self.collection)
def test_collection_list_filter(self):
response = self.client.get('/api/web/collections/?country_code=en', format='json')
data = response.json()
self.assertIn('count', data)
self.assertGreater(data['count'], 0)

View File

@ -6,7 +6,7 @@ from collection.views import common as views
app_name = 'collection' app_name = 'collection'
urlpatterns = [ urlpatterns = [
path('', views.CollectionListView.as_view(), name='list'), path('', views.CollectionHomePageView.as_view(), name='list'),
path('<slug:slug>/establishments/', views.CollectionEstablishmentListView.as_view(), path('<slug:slug>/establishments/', views.CollectionEstablishmentListView.as_view(),
name='detail'), name='detail'),

View File

@ -30,9 +30,26 @@ class CollectionListView(CollectionViewMixin, generics.ListAPIView):
def get_queryset(self): def get_queryset(self):
"""Override get_queryset method""" """Override get_queryset method"""
return models.Collection.objects.published()\ queryset = models.Collection.objects.published()\
.by_country_code(code=self.request.country_code)\ .by_country_code(code=self.request.country_code)\
.order_by('-on_top', '-created') .order_by('-on_top', '-created')
return queryset
class CollectionHomePageView(CollectionViewMixin, generics.ListAPIView):
"""List Collection view"""
permission_classes = (permissions.AllowAny,)
serializer_class = serializers.CollectionSerializer
def get_queryset(self):
"""Override get_queryset method"""
queryset = models.Collection.objects.published()\
.by_country_code(code=self.request.country_code)\
.filter_all_related_gt(3)\
.order_by('-on_top', '-modified')
return queryset
class CollectionEstablishmentListView(CollectionListView): class CollectionEstablishmentListView(CollectionListView):

View File

@ -0,0 +1,17 @@
# Generated by Django 2.2.4 on 2019-09-27 13:49
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('news', '0015_auto_20190927_0853'),
]
operations = [
migrations.RemoveField(
model_name='news',
name='author',
),
]

View File

@ -0,0 +1,14 @@
# Generated by Django 2.2.4 on 2019-09-27 14:32
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('news', '0017_auto_20190927_1403'),
('news', '0016_remove_news_author'),
]
operations = [
]

View File

@ -94,10 +94,15 @@ class News(BaseAttributes, TranslatedFieldsMixin):
slug = models.SlugField(unique=True, max_length=50, slug = models.SlugField(unique=True, max_length=50,
verbose_name=_('News slug')) verbose_name=_('News slug'))
playlist = models.IntegerField(_('playlist')) playlist = models.IntegerField(_('playlist'))
# author = models.CharField(max_length=255, blank=True, null=True,
# default=None,verbose_name=_('Author'))
state = models.PositiveSmallIntegerField(default=WAITING, choices=STATE_CHOICES, state = models.PositiveSmallIntegerField(default=WAITING, choices=STATE_CHOICES,
verbose_name=_('State')) verbose_name=_('State'))
author = models.CharField(max_length=255, blank=True, null=True, author = models.CharField(max_length=255, blank=True, null=True,
default=None,verbose_name=_('Author')) default=None,verbose_name=_('Author'))
is_highlighted = models.BooleanField(default=False, is_highlighted = models.BooleanField(default=False,
verbose_name=_('Is highlighted')) verbose_name=_('Is highlighted'))
# TODO: metadata_keys - описание ключей для динамического построения полей метаданных # TODO: metadata_keys - описание ключей для динамического построения полей метаданных

View File

@ -5,7 +5,7 @@ from location.serializers import CountrySimpleSerializer
from main.serializers import MetaDataContentSerializer from main.serializers import MetaDataContentSerializer
from news import models from news import models
from utils.serializers import TranslatedField from utils.serializers import TranslatedField
from account.serializers.common import UserSerializer
class NewsTypeSerializer(serializers.ModelSerializer): class NewsTypeSerializer(serializers.ModelSerializer):
"""News type serializer.""" """News type serializer."""
@ -50,6 +50,7 @@ class NewsDetailSerializer(NewsBaseSerializer):
description_translated = TranslatedField() description_translated = TranslatedField()
country = CountrySimpleSerializer(read_only=True) country = CountrySimpleSerializer(read_only=True)
author = UserSerializer(source='created_by')
state_display = serializers.CharField(source='get_state_display', state_display = serializers.CharField(source='get_state_display',
read_only=True) read_only=True)

View File

@ -1,6 +1,8 @@
"""Utils QuerySet Mixins""" """Utils QuerySet Mixins"""
from django.db import models from django.db import models
from django.db.models import Q, Sum, F
from functools import reduce
from operator import add
from utils.methods import get_contenttype from utils.methods import get_contenttype
@ -15,3 +17,40 @@ class ContentTypeQuerySetMixin(models.QuerySet):
"""Filter QuerySet by ContentType.""" """Filter QuerySet by ContentType."""
return self.filter(content_type=get_contenttype(app_label=app_label, return self.filter(content_type=get_contenttype(app_label=app_label,
model=model)) model=model))
class RelatedObjectsCountMixin(models.QuerySet):
"""QuerySet for ManyToMany related count filter"""
def _get_related_objects_names(self):
"""Get all related objects (with reversed)"""
related_objects_names = []
for related_object in self.model._meta.related_objects:
if isinstance(related_object, models.ManyToManyRel):
related_objects_names.append(related_object.name)
return related_objects_names
def _annotate_related_objects_count(self):
"""Annotate all related objects to queryset"""
annotations = {}
for related_object in self._get_related_objects_names():
annotations[f"{related_object}_count"] = models.Count(f"{related_object}")
return self.annotate(**annotations)
def filter_related_gt(self, count):
"""QuerySet filter by related objects count"""
q_objects = Q()
for related_object in self._get_related_objects_names():
q_objects.add(Q(**{f"{related_object}_count__gt": count}), Q.OR)
return self._annotate_related_objects_count().filter(q_objects)
def filter_all_related_gt(self, count):
"""Queryset filter by all related objects count"""
exp =reduce(add, [F(f"{related_object}_count") for related_object in self._get_related_objects_names()])
return self._annotate_related_objects_count()\
.annotate(all_related_count=exp)\
.filter(all_related_count__gt=count)