From 6cbfc38c9c159dde2c48b7278ac3dd3a3b1c1139 Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 17:58:39 +0300 Subject: [PATCH 01/26] Added back collections method for collection detail --- apps/collection/urls/back.py | 8 +++++++- apps/collection/views/back.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/collection/urls/back.py b/apps/collection/urls/back.py index 6a6dbd54..d7f77b9a 100644 --- a/apps/collection/urls/back.py +++ b/apps/collection/urls/back.py @@ -1,4 +1,5 @@ """Collection common urlpaths.""" +from django.urls import path from rest_framework.routers import SimpleRouter from collection.views import back as views @@ -7,4 +8,9 @@ app_name = 'collection' router = SimpleRouter() router.register(r'', views.CollectionBackOfficeViewSet) -urlpatterns = router.urls +urlpatterns = [ + path('//', views.CollectionBackOfficeView.as_view(), name='detail'), +] + +urlpatterns += router.urls + diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index a989ec56..65bd6c8b 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,3 +1,4 @@ +from rest_framework import generics from rest_framework import permissions from rest_framework import viewsets, mixins @@ -47,3 +48,12 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, collection.establishments.remove(related_object) elif obj_type == self.bind_object_serializer_class.PRODUCT: collection.products.remove(related_object) + + +class CollectionBackOfficeView(generics.GenericAPIView): + """ViewS for Collection model.""" + + pagination_class = None + permission_classes = (permissions.IsAuthenticated,) + queryset = models.Collection.objects.all() + serializer_class = serializers.CollectionBackOfficeSerializer From a6b77e74b541546c9f7a09e2fc8f7e519f8bdd16 Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 17:59:42 +0300 Subject: [PATCH 02/26] Remove unnecessary slash --- apps/collection/urls/back.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/collection/urls/back.py b/apps/collection/urls/back.py index d7f77b9a..f97a3945 100644 --- a/apps/collection/urls/back.py +++ b/apps/collection/urls/back.py @@ -9,7 +9,7 @@ router = SimpleRouter() router.register(r'', views.CollectionBackOfficeViewSet) urlpatterns = [ - path('//', views.CollectionBackOfficeView.as_view(), name='detail'), + path('/', views.CollectionBackOfficeView.as_view(), name='detail'), ] urlpatterns += router.urls From e0a66f300b76f8d60531f070aeb06c9b50c4cfb4 Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 18:07:04 +0300 Subject: [PATCH 03/26] Hide unnecessary fields --- apps/collection/serializers/back.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index 48c25f6c..6cedb087 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -33,11 +33,11 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): 'on_top', 'country', 'country_id', - 'block_size', - 'description', + # 'block_size', + # 'description', 'slug', - 'start', - 'end', + # 'start', + # 'end', 'count_related_objects', 'related_object_names', ] From 450ca4cf52aa105a082c1817756b65ebf31b057f Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 03:50:12 +0300 Subject: [PATCH 04/26] Added new field rank to collection --- apps/collection/models.py | 2 ++ apps/collection/serializers/back.py | 13 +++++++------ apps/collection/views/back.py | 8 +++++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index 7acd9991..14bd99c0 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -80,6 +80,8 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, verbose_name=_('Collection slug'), editable=True, null=True) old_id = models.IntegerField(null=True, blank=True) + rank = models.IntegerField(null=True, default=None) + objects = CollectionQuerySet.as_manager() class Meta: diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index 6cedb087..f41e3875 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -40,6 +40,7 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): # 'end', 'count_related_objects', 'related_object_names', + 'rank', ] @@ -68,15 +69,15 @@ class CollectionBindObjectSerializer(serializers.Serializer): attrs['collection'] = collection if obj_type == self.ESTABLISHMENT: - establishment = Establishment.objects.filter(pk=obj_id).\ + establishment = Establishment.objects.filter(pk=obj_id). \ first() if not establishment: raise BindingObjectNotFound() - if request.method == 'POST' and collection.establishments.\ + if request.method == 'POST' and collection.establishments. \ filter(pk=establishment.pk).exists(): raise ObjectAlreadyAdded() - if request.method == 'DELETE' and not collection.\ - establishments.filter(pk=establishment.pk).\ + if request.method == 'DELETE' and not collection. \ + establishments.filter(pk=establishment.pk). \ exists(): raise RemovedBindingObjectNotFound() attrs['related_object'] = establishment @@ -84,10 +85,10 @@ class CollectionBindObjectSerializer(serializers.Serializer): product = Product.objects.filter(pk=obj_id).first() if not product: raise BindingObjectNotFound() - if request.method == 'POST' and collection.products.\ + if request.method == 'POST' and collection.products. \ filter(pk=product.pk).exists(): raise ObjectAlreadyAdded() - if request.method == 'DELETE' and not collection.products.\ + if request.method == 'DELETE' and not collection.products. \ filter(pk=product.pk).exists(): raise RemovedBindingObjectNotFound() attrs['related_object'] = product diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index 65bd6c8b..67548c83 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,6 +1,7 @@ from rest_framework import generics from rest_framework import permissions -from rest_framework import viewsets, mixins +from rest_framework import viewsets +from rest_framework.response import Response from collection import models from collection.serializers import back as serializers @@ -49,6 +50,11 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, elif obj_type == self.bind_object_serializer_class.PRODUCT: collection.products.remove(related_object) + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()).order_by('rank', '-start') + serializer = self.get_serializer(queryset, many=True) + return Response(serializer.data) + class CollectionBackOfficeView(generics.GenericAPIView): """ViewS for Collection model.""" From 5c171c644cbc99a6905cbe0840b95f8c7416dd6f Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 03:52:52 +0300 Subject: [PATCH 05/26] Added mixins --- apps/collection/views/back.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index 67548c83..fdb441c2 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,4 +1,5 @@ from rest_framework import generics +from rest_framework import mixins from rest_framework import permissions from rest_framework import viewsets from rest_framework.response import Response From 8f6dd7e5c1c7bd8cd2cd14b21698119f0d298149 Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 16:17:35 +0300 Subject: [PATCH 06/26] Added related_object_ids --- apps/collection/models.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index 14bd99c0..d9256743 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -24,7 +24,8 @@ class CollectionNameMixin(models.Model): class CollectionDateMixin(models.Model): """CollectionDate mixin""" - start = models.DateTimeField(_('start')) + start = models.DateTimeField(blank=True, null=True, default=None, + verbose_name=_('start')) end = models.DateTimeField(blank=True, null=True, default=None, verbose_name=_('end')) @@ -110,20 +111,29 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, @property def related_object_names(self) -> list: """Return related object names.""" - raw_object_names = [] - for related_object in [related_object.name for related_object in self._related_objects]: - instances = getattr(self, f'{related_object}') + raw_object_names = {} + for related_object in [(related_object.id, related_object.name) for related_object in self._related_objects]: + instances = getattr(self, f'{related_object[1]}') if instances.exists(): for instance in instances.all(): - raw_object_names.append(instance.slug if hasattr(instance, 'slug') else None) + raw_object_names[related_object[0]] = instance.slug if hasattr(instance, 'slug') else None # parse slugs - object_names = [] + related_objects = [] + object_names = set() re_pattern = r'[\w]+' - for raw_name in raw_object_names: - result = re.findall(re_pattern, raw_name) - if result: object_names.append(' '.join(result).capitalize()) - return set(object_names) + for object_id in raw_object_names: + result = re.findall(re_pattern, raw_object_names[object_id]) + if result: + name = ' '.join(result).capitalize() + if name not in object_names: + related_objects.append({ + 'id': object_id, + 'name': name + }) + object_names.add(name) + + return related_objects class GuideTypeQuerySet(models.QuerySet): From 525658f39bae148af0e4845eacbd2d822338ba68 Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 18:32:06 +0300 Subject: [PATCH 07/26] Reformat ordering --- apps/collection/filters.py | 8 ++++++++ apps/collection/urls/back.py | 6 +----- apps/collection/views/back.py | 18 ++---------------- 3 files changed, 11 insertions(+), 21 deletions(-) create mode 100644 apps/collection/filters.py diff --git a/apps/collection/filters.py b/apps/collection/filters.py new file mode 100644 index 00000000..a97b47d1 --- /dev/null +++ b/apps/collection/filters.py @@ -0,0 +1,8 @@ +from rest_framework import filters + + +class CollectionBackOfficeOrderingFilter(filters.BaseFilterBackend): + """ Filter ordering """ + + def filter_queryset(self, request, queryset, view): + return queryset.order_by('rank', '-start') diff --git a/apps/collection/urls/back.py b/apps/collection/urls/back.py index f97a3945..972f5285 100644 --- a/apps/collection/urls/back.py +++ b/apps/collection/urls/back.py @@ -8,9 +8,5 @@ app_name = 'collection' router = SimpleRouter() router.register(r'', views.CollectionBackOfficeViewSet) -urlpatterns = [ - path('/', views.CollectionBackOfficeView.as_view(), name='detail'), -] - -urlpatterns += router.urls +urlpatterns = router.urls diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index fdb441c2..f9b119aa 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,9 +1,8 @@ -from rest_framework import generics from rest_framework import mixins from rest_framework import permissions from rest_framework import viewsets -from rest_framework.response import Response +from collection import filters from collection import models from collection.serializers import back as serializers from utils.views import BindObjectMixin @@ -28,6 +27,7 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, permission_classes = (permissions.IsAuthenticated,) queryset = models.Collection.objects.all() + filter_backends = [filters.CollectionBackOfficeOrderingFilter] serializer_class = serializers.CollectionBackOfficeSerializer bind_object_serializer_class = serializers.CollectionBindObjectSerializer @@ -50,17 +50,3 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, collection.establishments.remove(related_object) elif obj_type == self.bind_object_serializer_class.PRODUCT: collection.products.remove(related_object) - - def list(self, request, *args, **kwargs): - queryset = self.filter_queryset(self.get_queryset()).order_by('rank', '-start') - serializer = self.get_serializer(queryset, many=True) - return Response(serializer.data) - - -class CollectionBackOfficeView(generics.GenericAPIView): - """ViewS for Collection model.""" - - pagination_class = None - permission_classes = (permissions.IsAuthenticated,) - queryset = models.Collection.objects.all() - serializer_class = serializers.CollectionBackOfficeSerializer From 4eff4883697a3e06dd3fc2100007b6365d703b15 Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 21:39:09 +0300 Subject: [PATCH 08/26] Added description field --- apps/collection/serializers/back.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index f41e3875..c11f9fbf 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -34,7 +34,7 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): 'country', 'country_id', # 'block_size', - # 'description', + 'description', 'slug', # 'start', # 'end', From b847de11831fdc03dc6b3355b05d2881d76d8c08 Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 01:01:56 +0300 Subject: [PATCH 09/26] Added collection migration --- .../migrations/0024_auto_20191215_2156.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 apps/collection/migrations/0024_auto_20191215_2156.py diff --git a/apps/collection/migrations/0024_auto_20191215_2156.py b/apps/collection/migrations/0024_auto_20191215_2156.py new file mode 100644 index 00000000..6e11668e --- /dev/null +++ b/apps/collection/migrations/0024_auto_20191215_2156.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.7 on 2019-12-15 21:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('collection', '0023_advertorial'), + ] + + operations = [ + migrations.AddField( + model_name='collection', + name='rank', + field=models.IntegerField(default=None, null=True), + ), + migrations.AlterField( + model_name='collection', + name='start', + field=models.DateTimeField(blank=True, default=None, null=True, verbose_name='start'), + ), + ] From def1372317f409d457fd0a69c0b3fa740a54159f Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 01:02:21 +0300 Subject: [PATCH 10/26] Change ordering format --- apps/collection/filters.py | 8 -------- apps/collection/views/back.py | 8 ++++++-- 2 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 apps/collection/filters.py diff --git a/apps/collection/filters.py b/apps/collection/filters.py deleted file mode 100644 index a97b47d1..00000000 --- a/apps/collection/filters.py +++ /dev/null @@ -1,8 +0,0 @@ -from rest_framework import filters - - -class CollectionBackOfficeOrderingFilter(filters.BaseFilterBackend): - """ Filter ordering """ - - def filter_queryset(self, request, queryset, view): - return queryset.order_by('rank', '-start') diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index f9b119aa..787570cc 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,8 +1,9 @@ +from django_filters.rest_framework import DjangoFilterBackend from rest_framework import mixins from rest_framework import permissions from rest_framework import viewsets +from rest_framework.filters import OrderingFilter -from collection import filters from collection import models from collection.serializers import back as serializers from utils.views import BindObjectMixin @@ -27,10 +28,13 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, permission_classes = (permissions.IsAuthenticated,) queryset = models.Collection.objects.all() - filter_backends = [filters.CollectionBackOfficeOrderingFilter] + filter_backends = [DjangoFilterBackend, OrderingFilter] serializer_class = serializers.CollectionBackOfficeSerializer bind_object_serializer_class = serializers.CollectionBindObjectSerializer + ordering_fields = ('rank', 'start') + ordering = ('-start', ) + def perform_binding(self, serializer): data = serializer.validated_data collection = data.pop('collection') From a9f5a5b98f9338ac298e30e9b3ecf1784cff510f Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 13:34:54 +0300 Subject: [PATCH 11/26] Deleted description field --- apps/collection/migrations/0024_auto_20191215_2156.py | 4 ++++ apps/collection/models.py | 6 +++--- apps/collection/serializers/back.py | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/collection/migrations/0024_auto_20191215_2156.py b/apps/collection/migrations/0024_auto_20191215_2156.py index 6e11668e..1b494867 100644 --- a/apps/collection/migrations/0024_auto_20191215_2156.py +++ b/apps/collection/migrations/0024_auto_20191215_2156.py @@ -20,4 +20,8 @@ class Migration(migrations.Migration): name='start', field=models.DateTimeField(blank=True, default=None, null=True, verbose_name='start'), ), + migrations.RemoveField( + model_name='collection', + name='description', + ) ] diff --git a/apps/collection/models.py b/apps/collection/models.py index d9256743..be445394 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -74,9 +74,9 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, block_size = JSONField( _('collection block properties'), null=True, blank=True, default=None, help_text='{"width": "250px", "height":"250px"}') - description = TJSONField( - _('description'), null=True, blank=True, - default=None, help_text='{"en-GB":"some text"}') + # description = TJSONField( + # _('description'), null=True, blank=True, + # default=None, help_text='{"en-GB":"some text"}') slug = models.SlugField(max_length=50, unique=True, verbose_name=_('Collection slug'), editable=True, null=True) old_id = models.IntegerField(null=True, blank=True) diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index c11f9fbf..f41e3875 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -34,7 +34,7 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): 'country', 'country_id', # 'block_size', - 'description', + # 'description', 'slug', # 'start', # 'end', From c2a520b518655b6f6a3ce4443e717dd5979464fa Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 13:59:04 +0300 Subject: [PATCH 12/26] Reformat code style --- apps/collection/models.py | 7 ++++--- apps/collection/serializers/back.py | 3 ++- apps/collection/views/back.py | 4 +--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index be445394..099491ac 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -6,9 +6,10 @@ from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.utils.translation import gettext_lazy as _ -from utils.models import ProjectBaseMixin, URLImageMixin -from utils.models import TJSONField -from utils.models import TranslatedFieldsMixin +from utils.models import ( + ProjectBaseMixin, TJSONField, TranslatedFieldsMixin, + URLImageMixin, +) from utils.querysets import RelatedObjectsCountMixin diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index f41e3875..bdc97e91 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -7,7 +7,8 @@ from location.models import Country from location.serializers import CountrySimpleSerializer from product.models import Product from utils.exceptions import ( - BindingObjectNotFound, RemovedBindingObjectNotFound, ObjectAlreadyAdded + BindingObjectNotFound, ObjectAlreadyAdded, + RemovedBindingObjectNotFound, ) diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index 787570cc..0b13034b 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,7 +1,5 @@ from django_filters.rest_framework import DjangoFilterBackend -from rest_framework import mixins -from rest_framework import permissions -from rest_framework import viewsets +from rest_framework import mixins, permissions, viewsets from rest_framework.filters import OrderingFilter from collection import models From 33ac0ad3e6df423098efbe8dc9d4c50fa3f2d14d Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 14:03:44 +0300 Subject: [PATCH 13/26] Delete useless import --- apps/collection/urls/back.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/collection/urls/back.py b/apps/collection/urls/back.py index 972f5285..6a6dbd54 100644 --- a/apps/collection/urls/back.py +++ b/apps/collection/urls/back.py @@ -1,5 +1,4 @@ """Collection common urlpaths.""" -from django.urls import path from rest_framework.routers import SimpleRouter from collection.views import back as views @@ -9,4 +8,3 @@ router = SimpleRouter() router.register(r'', views.CollectionBackOfficeViewSet) urlpatterns = router.urls - From 586f6e373bc7563301e6ad177e21cfcc621f4617 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 15:30:05 +0300 Subject: [PATCH 14/26] Anatoly, dont erase working code during refactoring pls --- apps/establishment/models.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/establishment/models.py b/apps/establishment/models.py index ab7f14fa..5ff6f921 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -541,9 +541,15 @@ class Establishment(GalleryModelMixin, ProjectBaseMixin, URLImageMixin, def visible_tags(self): return super().visible_tags \ .exclude(category__index_name__in=['guide', 'collection', 'purchased_item', - 'business_tag', 'business_tags_de', 'tag']) + 'business_tag', 'business_tags_de']) \ + .exclude(value__in=['rss', 'rss_selection']) # todo: recalculate toque_number + @property + def visible_tags_detail(self): + """Removes some tags from detail Establishment representation""" + return self.visible_tags.exclude(category__index_name__in=['tag']) + def recalculate_toque_number(self): toque_number = 0 if self.address and self.public_mark: From fb05243281e36565dd01781e23fda398457f9fec Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 16:55:11 +0300 Subject: [PATCH 15/26] Change related_object field --- apps/collection/serializers/back.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index bdc97e91..d8472af1 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -21,7 +21,7 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): source='get_collection_type_display', read_only=True) country = CountrySimpleSerializer(read_only=True) count_related_objects = serializers.IntegerField(read_only=True) - related_object_names = serializers.ListField(read_only=True) + related_object_names = serializers.JSONField(read_only=True) class Meta: model = models.Collection @@ -35,7 +35,7 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): 'country', 'country_id', # 'block_size', - # 'description', + 'description', 'slug', # 'start', # 'end', From cf001b3aabbb215a833aef67ea5a691a1562fd35 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 17:02:45 +0300 Subject: [PATCH 16/26] return news object after binding --- apps/news/views.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/news/views.py b/apps/news/views.py index c8acb3ac..732228b4 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -1,7 +1,7 @@ """News app views.""" from django.conf import settings from django.shortcuts import get_object_or_404 -from rest_framework import generics, permissions +from rest_framework import generics, permissions, response from news import filters, models, serializers from rating.tasks import add_rating @@ -106,6 +106,14 @@ class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView, CreateDestroyGalleryViewMixin): """Resource for a create gallery for news for back-office users.""" serializer_class = serializers.NewsBackOfficeGallerySerializer + permission_classes = (permissions.AllowAny, ) + + def create(self, request, *args, **kwargs): + _ = super().create(request, *args, **kwargs) + news_qs = self.filter_queryset(self.get_queryset()) + return response.Response( + data=serializers.NewsDetailSerializer(get_object_or_404(news_qs, pk=kwargs.get('pk'))).data + ) def get_object(self): """ From f4fff47d68565a935da4f3165037874e49ef3379 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 17:04:52 +0300 Subject: [PATCH 17/26] return news object after binding #2 --- apps/news/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/news/views.py b/apps/news/views.py index 732228b4..f59ad2d6 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -106,7 +106,6 @@ class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView, CreateDestroyGalleryViewMixin): """Resource for a create gallery for news for back-office users.""" serializer_class = serializers.NewsBackOfficeGallerySerializer - permission_classes = (permissions.AllowAny, ) def create(self, request, *args, **kwargs): _ = super().create(request, *args, **kwargs) From b25f387c9be6af1dbfbdb3e09cf1dc5db3d682fa Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 17:29:01 +0300 Subject: [PATCH 18/26] news search --- apps/search_indexes/views.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index 4b18bea6..f088bf8b 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -61,11 +61,18 @@ class NewsDocumentViewSet(BaseDocumentViewSet): ) filter_fields = { + 'tags_id': { + 'field': 'tags.id', + 'lookups': [ + constants.LOOKUP_QUERY_IN, + constants.LOOKUP_QUERY_EXCLUDE, + ], + }, 'tag': { 'field': 'tags.id', 'lookups': [ constants.LOOKUP_QUERY_IN, - constants.LOOKUP_QUERY_EXCLUDE + constants.LOOKUP_QUERY_EXCLUDE, ] }, 'tag_value': { From e68142bf2eb63549c08288b900fd01cc1bb3a5f2 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 18:43:15 +0300 Subject: [PATCH 19/26] BO news list by country --- apps/news/views.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/news/views.py b/apps/news/views.py index f59ad2d6..fe9a75e7 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -99,7 +99,10 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView, def get_queryset(self): """Override get_queryset method.""" - return super().get_queryset().with_extended_related() + qs = super().get_queryset().with_extended_related() + if self.request.country_code: + qs = qs.by_country_code(self.request.country_code) + return qs class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView, From b09d3af35f20ee06593d5497b49dd53630d79130 Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 22:00:42 +0300 Subject: [PATCH 20/26] Hardcode collection description migrate --- .../migrations/0025_collection_description.py | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 apps/collection/migrations/0025_collection_description.py diff --git a/apps/collection/migrations/0025_collection_description.py b/apps/collection/migrations/0025_collection_description.py new file mode 100644 index 00000000..9aba311f --- /dev/null +++ b/apps/collection/migrations/0025_collection_description.py @@ -0,0 +1,171 @@ +# Generated by Django 2.2.7 on 2019-12-16 17:25 + +from django.db import migrations + +import utils.models + +DESCRIPTION_DATA = { + 1123: '{"en-GB": "Test description"}', + 1100: '{"en-GB": "東京 寿司 2019"}', + 1101: '{"en-GB": "東京 中国料理 2019"}', + 1102: '{"en-GB": "北海道セレクション 2019"}', + 1107: '{"en-GB": "Arad"}', + 1103: '{"en-GB": "北陸セレクション 2019"}', + 1104: '{"en-GB": "東海セレクション 2019"}', + 1105: '{"en-GB": "京都・神戸セレクション 2019"}', + 1106: '{"en-GB": "Noaptea Muzeelor"}', + 1108: '{"en-GB": "Bacău"}', + 1109: '{"en-GB": "Brăila"}', + 1110: '{"en-GB": "Constanța și litoral"}', + 1111: '{"en-GB": "Craiova"}', + 1112: '{"en-GB": "Galați"}', + 1113: '{"en-GB": "Iași"}', + 1114: '{"en-GB": "Pitești"}', + 1115: '{"en-GB": "Ploiești"}', + 1116: '{"en-GB": "17+ Club"}', + 1117: '{"en-GB": "Partener G&M: foodpanda"}', + 1118: '{"en-GB": "Partener G&M: Alpha Gold"}', + 1119: '{"en-GB": "Partener G&M: Bit Soft"}', + 1120: '{"en-GB": "Premiile Gault&Millau 2019"}', + 992: '{"en-GB": "Restaurants avec terrasse"}', + 994: '{"en-GB": "Restaurants ouverts le midi"}', + 986: '{"en-GB": "Les restaurants des lauréats"}', + 988: '{"en-GB": "Gagas de Pizza"}', + 993: '{"en-GB": "Restaurants apportez votre vin"}', + 997: '{"en-GB": "Les restaurants d\'hôtels"}', + 1033: '{"en-GB": "Restos: ça vient d\'ouvrir"}', + 998: '{"en-GB": "Restaurants de femmes chefs"}', + 990: '{"en-GB": "Ma claque du burger ?"}', + 989: '{"en-GB": "Ouverts avec Gault&Millau"}', + 1121: '{"en-GB": "POP"}', + 991: '{"en-GB": "Ma langue au matcha"}', + 987: '{"en-GB": "Marmites cosmopolites"}', + 985: '{"en-GB": "Nos tartares préférés"}', + 996: '{"en-GB": "Gastro-Bistro"}', + 1036: '{"en-GB": "Les belles viandes dans l\'assiette"}', + 995: '{"en-GB": "Cure de terrasses"}', + 1005: '{"en-GB": "Carte de vins remarquable"}', + 1009: '{"en-GB": "JRE"}', + 1007: '{"en-GB": "Embraisez qui vous voudrez"}', + 1022: '{"en-GB": "Les coffee shop"}', + 1000: '{"en-GB": "Great Views"}', + 1016: '{"en-GB": "Les terrasses de l\'été"}', + 1018: '{"en-GB": "POP"}', + 1004: '{"en-GB": "Prix-Plaisir"}', + 999: '{"en-GB": "Prix spéciaux fin de soirée"}', + 1001: '{"en-GB": "Exceptional Wine Lists"}', + 1012: '{"en-GB": "NorthSeaChefs"}', + 1011: '{"en-GB": "Ramen japonais et nouilles asiatiques"}', + 1008: '{"en-GB": "Pickles et cuisines acides"}', + 1002: '"{""en-GB"": ""Poke bowl', + 1013: '{"en-GB": "Coquillages et crustacés"}', + 1014: '{"en-GB": "Génération W"}', + 1015: '"{""en-GB"": ""Pita', + 1017: '{"en-GB": "Belles cartes des vins"}', + 1021: '{"en-GB": "Smiley FAVV/AFSCA"}', + 1010: '{"en-GB": "Mastercooks"}', + 1019: '{"en-GB": "Où manger les pieds dans l\'eau ?"}', + 1020: '{"en-GB": "Où siroter une petite mousse ? "}', + 1006: '{"en-GB": "Vegetarian Menus"}', + 1003: '{"en-GB": "BYO"}', + 1025: '{"en-GB": "Traditional Georgian"}', + 1024: '{"en-GB": "Les Grands de demain 2018"}', + 1043: '{"en-GB": "Top Gastro"}', + 1026: '{"en-GB": "Top Luxury"}', + 1028: '{"en-GB": "Gastronomic"}', + 1031: '{"en-GB": "Les dotés qui viennent d\'ouvrir"}', + 1029: '{"en-GB": "Wine Restaurant"}', + 1027: '{"en-GB": "Iconic Places"}', + 1032: '{"en-GB": "Les 5 dotés à 3 toques et plus"}', + 1047: '{"en-GB": "Our Mother\'s Day picks"}', + 1038: '{"en-GB": "Gastronomique"}', + 1023: '{"en-GB": "Jeunes Talents 2018"}', + 1040: '{"en-GB": "Our selection of pastry shops"}', + 1035: '{"en-GB": "Romantic Restaurants"}', + 1045: '{"en-GB": "Traditional cuisine"}', + 1039: '{"en-GB": "Les plus grands gastros français"}', + 1030: '{"en-GB": "Dotation G&M"}', + 1044: '{"en-GB": "Ca va ouvrir"}', + 1041: '{"en-GB": "Delicious lunch in Split"}', + 1034: '{"en-GB": "POPセレクション 2018"}', + 1046: '{"en-GB": "Romantic restaurants"}', + 1042: '{"en-GB": "Top Gastro"}', + 1037: '{"en-GB": "アワード受賞レストランに行きたい!"}', + 1048: '{"en-GB": "Top Long Lunch choices"}', + 1049: '{"en-GB": "Creative Degustation Menus"}', + 1050: '{"en-GB": "2018年 高評価レストラン"}', + 1069: '{"en-GB": "Discovery Cheque"}', + 1054: '{"en-GB": "restaurant vegan"}', + 1070: '{"en-GB": "Les Grands de Demain 2019"}', + 1063: '{"en-GB": "Kosher"}', + 1058: '{"en-GB": "Trophees 2018"}', + 1064: '{"en-GB": "Asian Restaurants"}', + 1061: '{"en-GB": "Business"}', + 1065: '{"en-GB": "Italian Restaurants"}', + 1051: '{"en-GB": "PoP"}', + 1057: '{"en-GB": "Les Patrons Cuisiniers"}', + 1067: '{"en-GB": "POP"}', + 1053: '{"en-GB": "Cocktail Bar"}', + 1062: '{"en-GB": "Romantic Restaurants"}', + 1072: '{"en-GB": "Top Gastro Antilles"}', + 1052: '{"en-GB": "Top Gastro"}', + 1078: '{"en-GB": "POPセレクション2019"}', + 1081: '{"en-GB": "Oradea"}', + 1083: '{"en-GB": "Sibiu"}', + 1085: '{"en-GB": "Destinații speciale"}', + 1086: '{"en-GB": "Premiile Gault&Millau 2018"}', + 1087: '{"en-GB": "Partener G&M: Nespresso"}', + 1088: '{"en-GB": "アワード受賞レストランに行きたい!2019"}', + 1089: '{"en-GB": "高評価レストラン 2019"}', + 1090: '{"en-GB": "Gault&Millau Croatia Trophies 2019"}', + 1091: '{"en-GB": "The best restaurants 2019"}', + 1092: '{"en-GB": "\"Yummy\" lunch in Rijeka"}', + 1093: '{"en-GB": "POP places in Zagreb"}', + 1094: '{"en-GB": "東京 フランス料理 2019"}', + 1095: '{"en-GB": "東京 日本料理 2019"}', + 1096: '{"en-GB": "東京 イタリア料理 2019"}', + 1097: '{"en-GB": "東京 スペイン料理 2019"}', + 1098: '{"en-GB": "東京 イノベーティブ 2019"}', + 1099: '{"en-GB": "Pește și fructe de mare"}', + 1056: '{"en-GB": "Alliance Gastronomique"}', + 1060: '{"en-GB": "Meat Restaurants"}', + 1068: '{"en-GB": "The Young Masters"}', + 1055: '{"en-GB": "JRE"}', + 1071: '{"en-GB": "Les Jeunes Talents 2019"}', + 1059: '{"en-GB": "Fish Restaurants"}', + 1066: '{"en-GB": "Best Cocktail Bars"}', + 1077: '{"en-GB": "POP"}', + 1074: '{"en-GB": "Vue Exceptionnelle"}', + 1073: '{"en-GB": "Peyi"}', + 1075: '{"en-GB": "Top Bar"}', + 1076: '{"en-GB": "Euro-Toques"}', + 1080: '{"en-GB": "Cluj-Napoca"}', + 1079: '{"en-GB": "București"}', + 1084: '{"en-GB": "Timișoara"}', + 1082: '{"en-GB": "Brașov"}', + 1128: '{"en-GB": "asdad2"}', +} + + +def adding_description(apps, schema_editor): + Collection = apps.get_model("collection", "Collection") + for collection in Collection.objects.all(): + collection.description = DESCRIPTION_DATA.get(collection.id) + collection.save() + + +class Migration(migrations.Migration): + dependencies = [ + ('collection', '0024_auto_20191215_2156'), + ] + + operations = [ + migrations.AddField( + model_name='collection', + name='description', + field=utils.models.TJSONField(blank=True, default=None, + help_text='{"en-GB":"some text"}', null=True, + verbose_name='description'), + ), + migrations.RunPython(adding_description), + ] From 10ca6d8932012a4bf6c86bc75c66957446cbd236 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 22:13:25 +0300 Subject: [PATCH 21/26] remove hardcode from migration --- .../migrations/0025_collection_description.py | 151 ------------------ 1 file changed, 151 deletions(-) diff --git a/apps/collection/migrations/0025_collection_description.py b/apps/collection/migrations/0025_collection_description.py index 9aba311f..d7638db3 100644 --- a/apps/collection/migrations/0025_collection_description.py +++ b/apps/collection/migrations/0025_collection_description.py @@ -4,156 +4,6 @@ from django.db import migrations import utils.models -DESCRIPTION_DATA = { - 1123: '{"en-GB": "Test description"}', - 1100: '{"en-GB": "東京 寿司 2019"}', - 1101: '{"en-GB": "東京 中国料理 2019"}', - 1102: '{"en-GB": "北海道セレクション 2019"}', - 1107: '{"en-GB": "Arad"}', - 1103: '{"en-GB": "北陸セレクション 2019"}', - 1104: '{"en-GB": "東海セレクション 2019"}', - 1105: '{"en-GB": "京都・神戸セレクション 2019"}', - 1106: '{"en-GB": "Noaptea Muzeelor"}', - 1108: '{"en-GB": "Bacău"}', - 1109: '{"en-GB": "Brăila"}', - 1110: '{"en-GB": "Constanța și litoral"}', - 1111: '{"en-GB": "Craiova"}', - 1112: '{"en-GB": "Galați"}', - 1113: '{"en-GB": "Iași"}', - 1114: '{"en-GB": "Pitești"}', - 1115: '{"en-GB": "Ploiești"}', - 1116: '{"en-GB": "17+ Club"}', - 1117: '{"en-GB": "Partener G&M: foodpanda"}', - 1118: '{"en-GB": "Partener G&M: Alpha Gold"}', - 1119: '{"en-GB": "Partener G&M: Bit Soft"}', - 1120: '{"en-GB": "Premiile Gault&Millau 2019"}', - 992: '{"en-GB": "Restaurants avec terrasse"}', - 994: '{"en-GB": "Restaurants ouverts le midi"}', - 986: '{"en-GB": "Les restaurants des lauréats"}', - 988: '{"en-GB": "Gagas de Pizza"}', - 993: '{"en-GB": "Restaurants apportez votre vin"}', - 997: '{"en-GB": "Les restaurants d\'hôtels"}', - 1033: '{"en-GB": "Restos: ça vient d\'ouvrir"}', - 998: '{"en-GB": "Restaurants de femmes chefs"}', - 990: '{"en-GB": "Ma claque du burger ?"}', - 989: '{"en-GB": "Ouverts avec Gault&Millau"}', - 1121: '{"en-GB": "POP"}', - 991: '{"en-GB": "Ma langue au matcha"}', - 987: '{"en-GB": "Marmites cosmopolites"}', - 985: '{"en-GB": "Nos tartares préférés"}', - 996: '{"en-GB": "Gastro-Bistro"}', - 1036: '{"en-GB": "Les belles viandes dans l\'assiette"}', - 995: '{"en-GB": "Cure de terrasses"}', - 1005: '{"en-GB": "Carte de vins remarquable"}', - 1009: '{"en-GB": "JRE"}', - 1007: '{"en-GB": "Embraisez qui vous voudrez"}', - 1022: '{"en-GB": "Les coffee shop"}', - 1000: '{"en-GB": "Great Views"}', - 1016: '{"en-GB": "Les terrasses de l\'été"}', - 1018: '{"en-GB": "POP"}', - 1004: '{"en-GB": "Prix-Plaisir"}', - 999: '{"en-GB": "Prix spéciaux fin de soirée"}', - 1001: '{"en-GB": "Exceptional Wine Lists"}', - 1012: '{"en-GB": "NorthSeaChefs"}', - 1011: '{"en-GB": "Ramen japonais et nouilles asiatiques"}', - 1008: '{"en-GB": "Pickles et cuisines acides"}', - 1002: '"{""en-GB"": ""Poke bowl', - 1013: '{"en-GB": "Coquillages et crustacés"}', - 1014: '{"en-GB": "Génération W"}', - 1015: '"{""en-GB"": ""Pita', - 1017: '{"en-GB": "Belles cartes des vins"}', - 1021: '{"en-GB": "Smiley FAVV/AFSCA"}', - 1010: '{"en-GB": "Mastercooks"}', - 1019: '{"en-GB": "Où manger les pieds dans l\'eau ?"}', - 1020: '{"en-GB": "Où siroter une petite mousse ? "}', - 1006: '{"en-GB": "Vegetarian Menus"}', - 1003: '{"en-GB": "BYO"}', - 1025: '{"en-GB": "Traditional Georgian"}', - 1024: '{"en-GB": "Les Grands de demain 2018"}', - 1043: '{"en-GB": "Top Gastro"}', - 1026: '{"en-GB": "Top Luxury"}', - 1028: '{"en-GB": "Gastronomic"}', - 1031: '{"en-GB": "Les dotés qui viennent d\'ouvrir"}', - 1029: '{"en-GB": "Wine Restaurant"}', - 1027: '{"en-GB": "Iconic Places"}', - 1032: '{"en-GB": "Les 5 dotés à 3 toques et plus"}', - 1047: '{"en-GB": "Our Mother\'s Day picks"}', - 1038: '{"en-GB": "Gastronomique"}', - 1023: '{"en-GB": "Jeunes Talents 2018"}', - 1040: '{"en-GB": "Our selection of pastry shops"}', - 1035: '{"en-GB": "Romantic Restaurants"}', - 1045: '{"en-GB": "Traditional cuisine"}', - 1039: '{"en-GB": "Les plus grands gastros français"}', - 1030: '{"en-GB": "Dotation G&M"}', - 1044: '{"en-GB": "Ca va ouvrir"}', - 1041: '{"en-GB": "Delicious lunch in Split"}', - 1034: '{"en-GB": "POPセレクション 2018"}', - 1046: '{"en-GB": "Romantic restaurants"}', - 1042: '{"en-GB": "Top Gastro"}', - 1037: '{"en-GB": "アワード受賞レストランに行きたい!"}', - 1048: '{"en-GB": "Top Long Lunch choices"}', - 1049: '{"en-GB": "Creative Degustation Menus"}', - 1050: '{"en-GB": "2018年 高評価レストラン"}', - 1069: '{"en-GB": "Discovery Cheque"}', - 1054: '{"en-GB": "restaurant vegan"}', - 1070: '{"en-GB": "Les Grands de Demain 2019"}', - 1063: '{"en-GB": "Kosher"}', - 1058: '{"en-GB": "Trophees 2018"}', - 1064: '{"en-GB": "Asian Restaurants"}', - 1061: '{"en-GB": "Business"}', - 1065: '{"en-GB": "Italian Restaurants"}', - 1051: '{"en-GB": "PoP"}', - 1057: '{"en-GB": "Les Patrons Cuisiniers"}', - 1067: '{"en-GB": "POP"}', - 1053: '{"en-GB": "Cocktail Bar"}', - 1062: '{"en-GB": "Romantic Restaurants"}', - 1072: '{"en-GB": "Top Gastro Antilles"}', - 1052: '{"en-GB": "Top Gastro"}', - 1078: '{"en-GB": "POPセレクション2019"}', - 1081: '{"en-GB": "Oradea"}', - 1083: '{"en-GB": "Sibiu"}', - 1085: '{"en-GB": "Destinații speciale"}', - 1086: '{"en-GB": "Premiile Gault&Millau 2018"}', - 1087: '{"en-GB": "Partener G&M: Nespresso"}', - 1088: '{"en-GB": "アワード受賞レストランに行きたい!2019"}', - 1089: '{"en-GB": "高評価レストラン 2019"}', - 1090: '{"en-GB": "Gault&Millau Croatia Trophies 2019"}', - 1091: '{"en-GB": "The best restaurants 2019"}', - 1092: '{"en-GB": "\"Yummy\" lunch in Rijeka"}', - 1093: '{"en-GB": "POP places in Zagreb"}', - 1094: '{"en-GB": "東京 フランス料理 2019"}', - 1095: '{"en-GB": "東京 日本料理 2019"}', - 1096: '{"en-GB": "東京 イタリア料理 2019"}', - 1097: '{"en-GB": "東京 スペイン料理 2019"}', - 1098: '{"en-GB": "東京 イノベーティブ 2019"}', - 1099: '{"en-GB": "Pește și fructe de mare"}', - 1056: '{"en-GB": "Alliance Gastronomique"}', - 1060: '{"en-GB": "Meat Restaurants"}', - 1068: '{"en-GB": "The Young Masters"}', - 1055: '{"en-GB": "JRE"}', - 1071: '{"en-GB": "Les Jeunes Talents 2019"}', - 1059: '{"en-GB": "Fish Restaurants"}', - 1066: '{"en-GB": "Best Cocktail Bars"}', - 1077: '{"en-GB": "POP"}', - 1074: '{"en-GB": "Vue Exceptionnelle"}', - 1073: '{"en-GB": "Peyi"}', - 1075: '{"en-GB": "Top Bar"}', - 1076: '{"en-GB": "Euro-Toques"}', - 1080: '{"en-GB": "Cluj-Napoca"}', - 1079: '{"en-GB": "București"}', - 1084: '{"en-GB": "Timișoara"}', - 1082: '{"en-GB": "Brașov"}', - 1128: '{"en-GB": "asdad2"}', -} - - -def adding_description(apps, schema_editor): - Collection = apps.get_model("collection", "Collection") - for collection in Collection.objects.all(): - collection.description = DESCRIPTION_DATA.get(collection.id) - collection.save() - - class Migration(migrations.Migration): dependencies = [ ('collection', '0024_auto_20191215_2156'), @@ -167,5 +17,4 @@ class Migration(migrations.Migration): help_text='{"en-GB":"some text"}', null=True, verbose_name='description'), ), - migrations.RunPython(adding_description), ] From 1545ca9035d5aca1fb949ee853264cc354d37c91 Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 22:26:14 +0300 Subject: [PATCH 22/26] Added description field --- apps/collection/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index 099491ac..5c2e081c 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -75,9 +75,9 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, block_size = JSONField( _('collection block properties'), null=True, blank=True, default=None, help_text='{"width": "250px", "height":"250px"}') - # description = TJSONField( - # _('description'), null=True, blank=True, - # default=None, help_text='{"en-GB":"some text"}') + description = TJSONField( + _('description'), null=True, blank=True, + default=None, help_text='{"en-GB":"some text"}') slug = models.SlugField(max_length=50, unique=True, verbose_name=_('Collection slug'), editable=True, null=True) old_id = models.IntegerField(null=True, blank=True) From 913da37b84934ded119f4ce26489d9e90beaeb99 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 22:26:38 +0300 Subject: [PATCH 23/26] return collections dsc field --- apps/collection/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index 099491ac..5c2e081c 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -75,9 +75,9 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, block_size = JSONField( _('collection block properties'), null=True, blank=True, default=None, help_text='{"width": "250px", "height":"250px"}') - # description = TJSONField( - # _('description'), null=True, blank=True, - # default=None, help_text='{"en-GB":"some text"}') + description = TJSONField( + _('description'), null=True, blank=True, + default=None, help_text='{"en-GB":"some text"}') slug = models.SlugField(max_length=50, unique=True, verbose_name=_('Collection slug'), editable=True, null=True) old_id = models.IntegerField(null=True, blank=True) From 04bada1cd186698847512e3dad66343aed644e36 Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 22:32:38 +0300 Subject: [PATCH 24/26] Fixed object names --- apps/collection/models.py | 15 +++++++++------ apps/collection/serializers/back.py | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index 5c2e081c..41e0118a 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -112,19 +112,22 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, @property def related_object_names(self) -> list: """Return related object names.""" - raw_object_names = {} - for related_object in [(related_object.id, related_object.name) for related_object in self._related_objects]: - instances = getattr(self, f'{related_object[1]}') + raw_objects = [] + for related_object in [related_object.name for related_object in self._related_objects]: + instances = getattr(self, f'{related_object}') if instances.exists(): for instance in instances.all(): - raw_object_names[related_object[0]] = instance.slug if hasattr(instance, 'slug') else None + raw_object = (instance.id, instance.slug) if hasattr(instance, 'slug') else ( + instance.id, None + ) + raw_objects.append(raw_object) # parse slugs related_objects = [] object_names = set() re_pattern = r'[\w]+' - for object_id in raw_object_names: - result = re.findall(re_pattern, raw_object_names[object_id]) + for object_id, raw_name, in raw_objects: + result = re.findall(re_pattern, raw_name) if result: name = ' '.join(result).capitalize() if name not in object_names: diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index d8472af1..35917142 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -21,7 +21,7 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): source='get_collection_type_display', read_only=True) country = CountrySimpleSerializer(read_only=True) count_related_objects = serializers.IntegerField(read_only=True) - related_object_names = serializers.JSONField(read_only=True) + related_object_names = serializers.ListField(read_only=True) class Meta: model = models.Collection From 0a25ec3e7ca421aba50017a65d778f4723f62a17 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 23:16:12 +0300 Subject: [PATCH 25/26] news duplication info --- .../migrations/0043_auto_20191216_1920.py | 37 +++++++++++++++++++ apps/news/models.py | 19 ++++++++-- apps/news/serializers.py | 16 ++++++++ 3 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 apps/news/migrations/0043_auto_20191216_1920.py diff --git a/apps/news/migrations/0043_auto_20191216_1920.py b/apps/news/migrations/0043_auto_20191216_1920.py new file mode 100644 index 00000000..03f5a991 --- /dev/null +++ b/apps/news/migrations/0043_auto_20191216_1920.py @@ -0,0 +1,37 @@ +# Generated by Django 2.2.7 on 2019-12-16 19:20 + +import django.contrib.postgres.fields.hstore +from django.db import migrations, models +import uuid + +def fill_uuid(apps, schemaeditor): + News = apps.get_model('news', 'News') + for news in News.objects.all(): + news.duplication_uuid = uuid.uuid4() + news.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0042_news_duplication_date'), + ] + + operations = [ + migrations.AddField( + model_name='news', + name='description_to_locale_is_active', + field=django.contrib.postgres.fields.hstore.HStoreField(blank=True, default=dict, help_text='{"en-GB": true, "fr-FR": false}', null=True, verbose_name='Is description for certain locale active'), + ), + migrations.AddField( + model_name='news', + name='duplication_uuid', + field=models.UUIDField(default=uuid.uuid4, verbose_name='Field to detect doubles'), + ), + migrations.AlterField( + model_name='news', + name='slugs', + field=django.contrib.postgres.fields.hstore.HStoreField(blank=True, default=dict, help_text='{"en-GB":"some slug"}', null=True, verbose_name='Slugs for current news obj'), + ), + migrations.RunPython(fill_uuid, migrations.RunPython.noop), + ] diff --git a/apps/news/models.py b/apps/news/models.py index 6ebdca76..9a463026 100644 --- a/apps/news/models.py +++ b/apps/news/models.py @@ -1,5 +1,9 @@ """News app models.""" +import uuid + +from django.conf import settings from django.contrib.contenttypes import fields as generic +from django.contrib.postgres.fields import HStoreField from django.db import models from django.db.models import Case, When from django.utils import timezone @@ -11,8 +15,6 @@ from utils.models import (BaseAttributes, TJSONField, TranslatedFieldsMixin, Has ProjectBaseMixin, GalleryModelMixin, IntermediateGalleryModelMixin, FavoritesMixin) from utils.querysets import TranslationQuerysetMixin -from django.conf import settings -from django.contrib.postgres.fields import HStoreField class Agenda(ProjectBaseMixin, TranslatedFieldsMixin): @@ -177,11 +179,14 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi description = TJSONField(blank=True, null=True, default=None, verbose_name=_('description'), help_text='{"en-GB":"some text"}') + description_to_locale_is_active = HStoreField(null=True, default=dict, blank=True, + verbose_name=_('Is description for certain locale active'), + help_text='{"en-GB": true, "fr-FR": false}') start = models.DateTimeField(blank=True, null=True, default=None, verbose_name=_('Start')) end = models.DateTimeField(blank=True, null=True, default=None, verbose_name=_('End')) - slugs = HStoreField(null=True, blank=True, default=None, + slugs = HStoreField(null=True, blank=True, default=dict, verbose_name=_('Slugs for current news obj'), help_text='{"en-GB":"some slug"}') state = models.PositiveSmallIntegerField(default=WAITING, choices=STATE_CHOICES, @@ -213,6 +218,8 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi on_delete=models.SET_NULL, verbose_name=_('site settings')) duplication_date = models.DateTimeField(blank=True, null=True, default=None, verbose_name=_('Duplication datetime')) + duplication_uuid = models.UUIDField(default=uuid.uuid4, editable=True, unique=False, + verbose_name=_('Field to detect doubles')) objects = NewsQuerySet.as_manager() class Meta: @@ -233,6 +240,12 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi self.duplication_date = timezone.now() self.save() + + @property + def duplicates(self): + """Duplicates for this news item excluding same country code labeled""" + return News.objects.filter(duplication_uuid=self.duplication_uuid).exclude(country=self.country) + @property def is_publish(self): return self.state in self.PUBLISHED_STATES diff --git a/apps/news/serializers.py b/apps/news/serializers.py index 5b9a8162..59076776 100644 --- a/apps/news/serializers.py +++ b/apps/news/serializers.py @@ -209,6 +209,20 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer): return super().update(instance, validated_data) +class NewsBackOfficeDuplicationInfoSerializer(serializers.ModelSerializer): + """Duplication info for news detail.""" + + country = CountrySimpleSerializer(read_only=True) + + class Meta: + model = models.News + fields = ( + 'id', + 'duplication_date', + 'country', + ) + + class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer, NewsDetailSerializer): """News detail serializer for back-office users.""" @@ -224,6 +238,7 @@ class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer, queryset=SiteSettings.objects.all()) template_display = serializers.CharField(source='get_template_display', read_only=True) + duplicates = NewsBackOfficeDuplicationInfoSerializer(many=True, allow_null=True, read_only=True) class Meta(NewsBackOfficeBaseSerializer.Meta, NewsDetailSerializer.Meta): """Meta class.""" @@ -237,6 +252,7 @@ class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer, 'template', 'template_display', 'is_international', + 'duplicates', ) From b34ab11fd881ef98244895254ff84c6326b93260 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 23:48:55 +0300 Subject: [PATCH 26/26] description news availability management from BO --- .../news/migrations/0044_auto_20191216_2044.py | 18 ++++++++++++++++++ apps/news/models.py | 2 +- apps/news/serializers.py | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 apps/news/migrations/0044_auto_20191216_2044.py diff --git a/apps/news/migrations/0044_auto_20191216_2044.py b/apps/news/migrations/0044_auto_20191216_2044.py new file mode 100644 index 00000000..3854cc70 --- /dev/null +++ b/apps/news/migrations/0044_auto_20191216_2044.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.7 on 2019-12-16 20:44 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0043_auto_20191216_1920'), + ] + + operations = [ + migrations.RenameField( + model_name='news', + old_name='description_to_locale_is_active', + new_name='locale_to_description_is_active', + ), + ] diff --git a/apps/news/models.py b/apps/news/models.py index 9a463026..149b8480 100644 --- a/apps/news/models.py +++ b/apps/news/models.py @@ -179,7 +179,7 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi description = TJSONField(blank=True, null=True, default=None, verbose_name=_('description'), help_text='{"en-GB":"some text"}') - description_to_locale_is_active = HStoreField(null=True, default=dict, blank=True, + locale_to_description_is_active = HStoreField(null=True, default=dict, blank=True, verbose_name=_('Is description for certain locale active'), help_text='{"en-GB": true, "fr-FR": false}') start = models.DateTimeField(blank=True, null=True, default=None, diff --git a/apps/news/serializers.py b/apps/news/serializers.py index 59076776..ad29f1ac 100644 --- a/apps/news/serializers.py +++ b/apps/news/serializers.py @@ -182,6 +182,7 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer): 'backoffice_title', 'subtitle', 'slugs', + 'locale_to_description_is_active', 'is_published', 'duplication_date', )