diff --git a/apps/account/migrations/0016_auto_20191024_0833.py b/apps/account/migrations/0016_auto_20191024_0833.py new file mode 100644 index 00000000..6c99d567 --- /dev/null +++ b/apps/account/migrations/0016_auto_20191024_0833.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.4 on 2019-10-24 08:33 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0015_merge_20191023_1317'), + ] + + operations = [ + migrations.AlterField( + model_name='role', + name='role', + field=models.PositiveIntegerField(choices=[(1, 'Standard user'), (2, 'Comments moderator'), (3, 'Country admin'), (4, 'Content page manager'), (5, 'Establishment manager'), (6, 'Reviewer manager'), (7, 'Restaurant reviewer')], verbose_name='Role'), + ), + migrations.AlterField( + model_name='userrole', + name='establishment', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='establishment.Establishment', verbose_name='Establishment'), + ), + ] diff --git a/apps/account/migrations/0017_merge_20191024_1233.py b/apps/account/migrations/0017_merge_20191024_1233.py new file mode 100644 index 00000000..580f6b2f --- /dev/null +++ b/apps/account/migrations/0017_merge_20191024_1233.py @@ -0,0 +1,14 @@ +# Generated by Django 2.2.4 on 2019-10-24 12:33 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0016_auto_20191024_0830'), + ('account', '0016_auto_20191024_0833'), + ] + + operations = [ + ] diff --git a/apps/advertisement/migrations/0004_auto_20191025_0903.py b/apps/advertisement/migrations/0004_auto_20191025_0903.py new file mode 100644 index 00000000..f633d67c --- /dev/null +++ b/apps/advertisement/migrations/0004_auto_20191025_0903.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.4 on 2019-10-25 09:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('advertisement', '0003_auto_20190919_1344'), + ] + + operations = [ + migrations.AlterField( + model_name='advertisement', + name='block_level', + field=models.CharField(blank=True, max_length=10, null=True, verbose_name='Block level'), + ), + ] diff --git a/apps/advertisement/models.py b/apps/advertisement/models.py index fdc25988..62b41428 100644 --- a/apps/advertisement/models.py +++ b/apps/advertisement/models.py @@ -15,7 +15,7 @@ class Advertisement(ImageMixin, ProjectBaseMixin, PlatformMixin): url = models.URLField(verbose_name=_('Ad URL')) width = models.PositiveIntegerField(verbose_name=_('Block width')) height = models.PositiveIntegerField(verbose_name=_('Block height')) - block_level = models.CharField(verbose_name=_('Block level'), max_length=10) + block_level = models.CharField(verbose_name=_('Block level'), max_length=10, blank=True, null=True) target_languages = models.ManyToManyField(Language) class Meta: diff --git a/apps/advertisement/transfer_data.py b/apps/advertisement/transfer_data.py new file mode 100644 index 00000000..3af16286 --- /dev/null +++ b/apps/advertisement/transfer_data.py @@ -0,0 +1,20 @@ +from pprint import pprint +from django.db.models import Value, IntegerField, F +from transfer.models import Ads +from transfer.serializers.advertisement import AdvertisementSerializer + + +def transfer_advertisement(): + queryset = Ads.objects.filter(href__isnull=False) + + serialized_data = AdvertisementSerializer(data=list(queryset.values()), many=True) + + if serialized_data.is_valid(): + serialized_data.save() + else: + pprint(f"News serializer errors: {serialized_data.errors}") + + +data_types = { + "commercial": [transfer_advertisement] +} \ No newline at end of file diff --git a/apps/collection/migrations/0016_auto_20191024_1334.py b/apps/collection/migrations/0016_auto_20191024_1334.py new file mode 100644 index 00000000..a362777f --- /dev/null +++ b/apps/collection/migrations/0016_auto_20191024_1334.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.4 on 2019-10-24 13:34 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('collection', '0015_auto_20191023_0715'), + ] + + operations = [ + migrations.AlterField( + model_name='guide', + name='collection', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='collection.Collection', verbose_name='collection'), + ), + ] diff --git a/apps/collection/models.py b/apps/collection/models.py index 0a2700bd..cbcc3842 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -101,8 +101,9 @@ class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin): advertorials = JSONField( _('advertorials'), null=True, blank=True, default=None, help_text='{"key":"value"}') - collection = models.ForeignKey( - Collection, verbose_name=_('collection'), on_delete=models.CASCADE) + collection = models.ForeignKey(Collection, on_delete=models.CASCADE, + null=True, blank=True, default=None, + verbose_name=_('collection')) objects = GuideQuerySet.as_manager() diff --git a/apps/establishment/migrations/0043_establishment_currency.py b/apps/establishment/migrations/0043_establishment_currency.py new file mode 100644 index 00000000..7c324dc4 --- /dev/null +++ b/apps/establishment/migrations/0043_establishment_currency.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.4 on 2019-10-24 13:13 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0022_auto_20191023_1113'), + ('establishment', '0042_establishment_tz'), + ] + + operations = [ + migrations.AddField( + model_name='establishment', + name='currency', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='main.Currency', verbose_name='currency'), + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 7de88d91..304ea2a6 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -17,7 +17,7 @@ from phonenumber_field.modelfields import PhoneNumberField from collection.models import Collection from location.models import Address -from main.models import Award +from main.models import Award, Currency from review.models import Review from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin, TranslatedFieldsMixin, BaseAttributes) @@ -362,6 +362,9 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin): reviews = generic.GenericRelation(to='review.Review') comments = generic.GenericRelation(to='comment.Comment') favorites = generic.GenericRelation(to='favorites.Favorites') + currency = models.ForeignKey(Currency, blank=True, null=True, default=None, + on_delete=models.PROTECT, + verbose_name=_('currency')) objects = EstablishmentQuerySet.as_manager() diff --git a/apps/establishment/serializers/back.py b/apps/establishment/serializers/back.py index 714dd62d..f1fb40a5 100644 --- a/apps/establishment/serializers/back.py +++ b/apps/establishment/serializers/back.py @@ -7,6 +7,7 @@ from establishment.serializers import ( EstablishmentTypeBaseSerializer) from main.models import Currency from utils.decorators import with_base_attributes +from utils.serializers import TimeZoneChoiceField class EstablishmentListCreateSerializer(EstablishmentBaseSerializer): @@ -19,8 +20,8 @@ class EstablishmentListCreateSerializer(EstablishmentBaseSerializer): phones = ContactPhonesSerializer(read_only=True, many=True, ) emails = ContactEmailsSerializer(read_only=True, many=True, ) socials = SocialNetworkRelatedSerializers(read_only=True, many=True, ) - slug = serializers.SlugField(required=True, allow_blank=False, max_length=50) type = EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True) + tz = TimeZoneChoiceField() class Meta: model = models.Establishment diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py index 389d0d1c..2846c5c8 100644 --- a/apps/establishment/serializers/common.py +++ b/apps/establishment/serializers/common.py @@ -159,10 +159,10 @@ class EstablishmentBaseSerializer(ProjectModelSerializer): """Base serializer for Establishment model.""" preview_image = serializers.URLField(source='preview_image_url') - slug = serializers.SlugField(allow_blank=False, required=True, max_length=50) address = AddressBaseSerializer() in_favorites = serializers.BooleanField(allow_null=True) tags = TagBaseSerializer(read_only=True, many=True) + currency = CurrencySerializer() class Meta: """Meta class.""" @@ -180,6 +180,7 @@ class EstablishmentBaseSerializer(ProjectModelSerializer): 'in_favorites', 'address', 'tags', + 'currency' ] diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index a1d8fcb5..43aa62c6 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -9,6 +9,7 @@ from establishment.models import Establishment, EstablishmentType, Menu from translation.models import Language from account.models import Role, UserRole from location.models import Country, Address, City, Region +from pytz import timezone as py_tz class BaseTestCase(APITestCase): @@ -77,7 +78,8 @@ class EstablishmentBTests(BaseTestCase): 'name': 'Test establishment', 'type_id': self.establishment_type.id, 'is_publish': True, - 'slug': 'test-establishment-slug' + 'slug': 'test-establishment-slug', + 'tz': py_tz('Europe/Moscow').zone } response = self.client.post('/api/back/establishments/', data=data, format='json') diff --git a/apps/favorites/tests.py b/apps/favorites/tests.py index dd5c6c4f..cebd43c2 100644 --- a/apps/favorites/tests.py +++ b/apps/favorites/tests.py @@ -1,14 +1,16 @@ # Create your tests here. from http.cookies import SimpleCookie -from django.contrib.contenttypes.models import ContentType -from rest_framework.test import APITestCase +from django.contrib.contenttypes.models import ContentType +from django.urls import reverse from rest_framework import status +from rest_framework.test import APITestCase from account.models import User +from establishment.models import Establishment, EstablishmentType from favorites.models import Favorites -from establishment.models import Establishment, EstablishmentType, EstablishmentSubType from news.models import NewsType, News +from datetime import datetime class BaseTestCase(APITestCase): @@ -17,38 +19,57 @@ class BaseTestCase(APITestCase): self.username = 'sedragurda' self.password = 'sedragurdaredips19' self.email = 'sedragurda@desoz.com' - self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password) - tokkens = User.create_jwt_tokens(self.user) - self.client.cookies = SimpleCookie({'access_token': tokkens.get('access_token'), - 'refresh_token': tokkens.get('refresh_token')}) + self.user = User.objects.create_user( + username=self.username, + email=self.email, + password=self.password + ) - self.test_news_type = NewsType.objects.create(name="Test news type") - self.test_news = News.objects.create(created_by=self.user, modified_by=self.user, title={"en-GB": "Test news"}, - news_type=self.test_news_type, - description={"en-GB": "Description test news"}, - start="2020-12-03 12:00:00", end="2020-12-13 12:00:00", - state=News.PUBLISHED, slug='test-news') + tokens = User.create_jwt_tokens(self.user) + self.client.cookies = SimpleCookie( + {'access_token': tokens.get('access_token'), + 'refresh_token': tokens.get('refresh_token')}) - self.test_content_type = ContentType.objects.get(app_label="news", model="news") + self.test_news_type = NewsType.objects.create( + name="Test news type", + ) + self.test_news = News.objects.create( + created_by=self.user, + modified_by=self.user, + title={"en-GB": "Test news"}, + news_type=self.test_news_type, + description={"en-GB": "Description test news"}, + start=datetime.fromisoformat("2020-12-03 12:00:00"), + end=datetime.fromisoformat("2020-12-03 12:00:00"), + state=News.PUBLISHED, + slug='test-news' + ) - self.test_favorites = Favorites.objects.create(user=self.user, content_type=self.test_content_type, - object_id=self.test_news.id) + self.test_content_type = ContentType.objects.get( + app_label="news", model="news") - self.test_establishment_type = EstablishmentType.objects.create(name={"en-GB": "test establishment type"}, - use_subtypes=False) + self.test_favorites = Favorites.objects.create( + user=self.user, content_type=self.test_content_type, + object_id=self.test_news.id) - self.test_establishment = Establishment.objects.create(name="test establishment", - description={"en-GB": "description of test establishment"}, - establishment_type=self.test_establishment_type, - is_publish=True) + self.test_establishment_type = EstablishmentType.objects.create( + name={"en-GB": "test establishment type"}, + use_subtypes=False) + + self.test_establishment = Establishment.objects.create( + name="test establishment", + description={"en-GB": "description of test establishment"}, + establishment_type=self.test_establishment_type, + is_publish=True) # value for GenericRelation(reverse side) field must be iterable - # value for GenericRelation(reverse side) field must be assigned through "set" method of field + # value for GenericRelation(reverse side) field must be assigned through + # "set" method of field self.test_establishment.favorites.set([self.test_favorites]) class FavoritesTestCase(BaseTestCase): def test_func(self): - response = self.client.get("/api/web/favorites/establishments/") - print(response.json()) + url = reverse('web:favorites:establishment-list') + response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) \ No newline at end of file diff --git a/apps/gallery/migrations/0004_merge_20191025_0906.py b/apps/gallery/migrations/0004_merge_20191025_0906.py new file mode 100644 index 00000000..4372fa95 --- /dev/null +++ b/apps/gallery/migrations/0004_merge_20191025_0906.py @@ -0,0 +1,14 @@ +# Generated by Django 2.2.4 on 2019-10-25 09:06 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('gallery', '0002_auto_20191023_1207'), + ('gallery', '0003_auto_20191003_1228'), + ] + + operations = [ + ] diff --git a/apps/main/serializers.py b/apps/main/serializers.py index 8975af14..a0af662b 100644 --- a/apps/main/serializers.py +++ b/apps/main/serializers.py @@ -4,7 +4,7 @@ from rest_framework import serializers from advertisement.serializers.web import AdvertisementSerializer from location.serializers import CountrySerializer from main import models -from utils.serializers import ProjectModelSerializer +from utils.serializers import ProjectModelSerializer, TranslatedField class FeatureSerializer(serializers.ModelSerializer): @@ -41,7 +41,9 @@ class SiteFeatureSerializer(serializers.ModelSerializer): class CurrencySerializer(ProjectModelSerializer): - """Currency serializer""" + """Currency serializer.""" + + name_translated = TranslatedField() class Meta: model = models.Currency diff --git a/apps/news/migrations/0028_auto_20191024_1649.py b/apps/news/migrations/0028_auto_20191024_1649.py new file mode 100644 index 00000000..c9eaacb1 --- /dev/null +++ b/apps/news/migrations/0028_auto_20191024_1649.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.4 on 2019-10-24 16:49 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0027_remove_news_playlist'), + ] + + operations = [ + migrations.AlterField( + model_name='newsgallery', + name='image', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='news_gallery', to='gallery.Image', verbose_name='gallery'), + ), + migrations.AlterField( + model_name='newsgallery', + name='news', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='news_gallery', to='news.News', verbose_name='news'), + ), + migrations.AlterUniqueTogether( + name='newsgallery', + unique_together={('news', 'is_main')}, + ), + ] diff --git a/apps/news/migrations/0029_merge_20191025_0906.py b/apps/news/migrations/0029_merge_20191025_0906.py new file mode 100644 index 00000000..e5967a8d --- /dev/null +++ b/apps/news/migrations/0029_merge_20191025_0906.py @@ -0,0 +1,14 @@ +# Generated by Django 2.2.4 on 2019-10-25 09:06 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0028_auto_20191024_1649'), + ('news', '0021_auto_20191021_1120'), + ] + + operations = [ + ] diff --git a/apps/news/models.py b/apps/news/models.py index a2130fac..dbb2f5bf 100644 --- a/apps/news/models.py +++ b/apps/news/models.py @@ -194,13 +194,24 @@ class News(BaseAttributes, TranslatedFieldsMixin): @property def main_image(self): - return self.news_gallery.main_images().first().image + qs = self.news_gallery.main_image() + if qs.exists(): + return qs.first().image + + @property + def image_url(self): + return self.main_image.image.url if self.main_image else None + + @property + def preview_image_url(self): + if self.main_image: + return self.main_image.get_image_url(thumbnail_key='news_preview') class NewsGalleryQuerySet(models.QuerySet): """QuerySet for model News""" - def main_images(self): + def main_image(self): """Return objects with flag is_main is True""" return self.filter(is_main=True) @@ -209,11 +220,11 @@ class NewsGallery(models.Model): news = models.ForeignKey(News, null=True, related_name='news_gallery', - on_delete=models.SET_NULL, + on_delete=models.CASCADE, verbose_name=_('news')) image = models.ForeignKey('gallery.Image', null=True, related_name='news_gallery', - on_delete=models.SET_NULL, + on_delete=models.CASCADE, verbose_name=_('gallery')) is_main = models.BooleanField(default=False, verbose_name=_('Is the main image')) @@ -224,3 +235,4 @@ class NewsGallery(models.Model): """NewsGallery meta class.""" verbose_name = _('news gallery') verbose_name_plural = _('news galleries') + unique_together = ('news', 'is_main') diff --git a/apps/news/serializers.py b/apps/news/serializers.py index 31c8fc91..2b4e98b6 100644 --- a/apps/news/serializers.py +++ b/apps/news/serializers.py @@ -281,7 +281,7 @@ class NewsBackOfficeGallerySerializer(serializers.ModelSerializer): if news.news_gallery.filter(image=image).exists(): raise serializers.ValidationError({'detail': _('Image is already added')}) - if is_main and news.news_gallery.main_images().exists(): + if is_main and news.news_gallery.main_image().exists(): raise serializers.ValidationError({'detail': _('Main image is already added')}) attrs['news'] = news diff --git a/apps/news/tests.py b/apps/news/tests.py index f5340d15..115763e5 100644 --- a/apps/news/tests.py +++ b/apps/news/tests.py @@ -18,11 +18,14 @@ class BaseTestCase(APITestCase): self.username = 'sedragurda' self.password = 'sedragurdaredips19' self.email = 'sedragurda@desoz.com' - self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password) - #get tokkens - tokkens = User.create_jwt_tokens(self.user) - self.client.cookies = SimpleCookie({'access_token': tokkens.get('access_token'), - 'refresh_token': tokkens.get('refresh_token')}) + self.user = User.objects.create_user( + username=self.username, email=self.email, password=self.password) + + # get tokens + tokens = User.create_jwt_tokens(self.user) + self.client.cookies = SimpleCookie( + {'access_token': tokens.get('access_token'), + 'refresh_token': tokens.get('refresh_token')}) self.test_news_type = NewsType.objects.create(name="Test news type") self.lang = Language.objects.get( @@ -46,21 +49,25 @@ class BaseTestCase(APITestCase): ) user_role.save() - self.test_news = News.objects.create(created_by=self.user, modified_by=self.user, - title={"en-GB": "Test news"}, - news_type=self.test_news_type, - description={"en-GB": "Description test news"}, - start=datetime.now() + timedelta(hours=-2), - end=datetime.now() + timedelta(hours=2), - state=News.PUBLISHED, slug='test-news-slug', - country=self.country_ru) + self.test_news = News.objects.create( + created_by=self.user, modified_by=self.user, + title={"en-GB": "Test news"}, + news_type=self.test_news_type, + description={"en-GB": "Description test news"}, + start=datetime.now() + timedelta(hours=-2), + end=datetime.now() + timedelta(hours=2), + state=News.PUBLISHED, + slug='test-news-slug', + country=self.country_ru, + ) + class NewsTestCase(BaseTestCase): def setUp(self): super().setUp() def test_web_news(self): - response = self.client.get("/api/web/news/") + response = self.client.get(reverse('web:news:list')) self.assertEqual(response.status_code, status.HTTP_200_OK) response = self.client.get(f"/api/web/news/slug/{self.test_news.slug}/") diff --git a/apps/news/urls/back.py b/apps/news/urls/back.py index 4ab11727..9cc3d94a 100644 --- a/apps/news/urls/back.py +++ b/apps/news/urls/back.py @@ -8,7 +8,7 @@ app_name = 'news' urlpatterns = [ path('', views.NewsBackOfficeLCView.as_view(), name='list-create'), path('/', views.NewsBackOfficeRUDView.as_view(), - name='gallery-retrieve-update-destroy'), + name='retrieve-update-destroy'), path('/gallery/', views.NewsBackOfficeGalleryListView.as_view(), name='gallery-list'), path('/gallery//', views.NewsBackOfficeGalleryCreateDestroyView.as_view(), diff --git a/apps/news/views.py b/apps/news/views.py index e0034afa..9cd5d969 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -14,14 +14,33 @@ from utils.permissions import IsCountryAdmin, IsContentPageManager class NewsMixinView: """News mixin.""" - permission_classes = (permissions.AllowAny, ) + permission_classes = (permissions.AllowAny,) + serializer_class = serializers.NewsBaseSerializer def get_queryset(self, *args, **kwargs): + from django.conf import settings """Override get_queryset method.""" - qs = models.News.objects.published().with_base_related()\ + + qs = models.News.objects.published().with_base_related() \ .order_by('-is_highlighted', '-created') - if self.request.country_code: - qs = qs.by_country_code(self.request.country_code) + country_code = self.request.country_code + if country_code: + + # temp code + # Temporary stub for international news logic + # (по договорённости с заказчиком на демонстрации 4 ноября + # здесь будет 6 фиксированных новостей) + # TODO replace this stub with actual logic + if hasattr(settings, 'HARDCODED_INTERNATIONAL_NEWS_IDS'): + if country_code and country_code != 'www' and country_code != 'main': + qs = qs.by_country_code(country_code) + else: + qs = models.News.objects.filter( + id__in=settings.HARDCODED_INTERNATIONAL_NEWS_IDS) + return qs + # temp code + + qs = qs.by_country_code(country_code) return qs diff --git a/apps/search_indexes/documents/news.py b/apps/search_indexes/documents/news.py index 699a1cca..86b117e5 100644 --- a/apps/search_indexes/documents/news.py +++ b/apps/search_indexes/documents/news.py @@ -24,6 +24,8 @@ class NewsDocument(Document): country = fields.ObjectField(properties={'id': fields.IntegerField(), 'code': fields.KeywordField()}) web_url = fields.KeywordField(attr='web_url') + image_url = fields.KeywordField(attr='image_url') + preview_image_url = fields.KeywordField(attr='preview_image_url') tags = fields.ObjectField( properties={ 'id': fields.IntegerField(attr='id'), diff --git a/apps/search_indexes/serializers.py b/apps/search_indexes/serializers.py index 535974a9..d4ab2dbf 100644 --- a/apps/search_indexes/serializers.py +++ b/apps/search_indexes/serializers.py @@ -102,28 +102,3 @@ class EstablishmentDocumentSerializer(DocumentSerializer): # 'establishment_type', # 'establishment_subtypes', ) - - - # def to_representation(self, instance): - # ret = super().to_representation(instance) - # dict_merge = lambda a, b: a.update(b) or a - # - # ret['tags'] = map(lambda tag: dict_merge(tag, {'label_translated': get_translated_value(tag.pop('label'))}), - # ret['tags']) - # ret['establishment_subtypes'] = map( - # lambda subtype: dict_merge(subtype, {'name_translated': get_translated_value(subtype.pop('name'))}), - # ret['establishment_subtypes']) - # if ret.get('establishment_type'): - # ret['establishment_type']['name_translated'] = get_translated_value(ret['establishment_type'].pop('name')) - # if ret.get('address'): - # ret['address']['city']['country']['name_translated'] = get_translated_value( - # ret['address']['city']['country'].pop('name')) - # location = ret['address'].pop('location') - # if location: - # ret['address']['geo_lon'] = location['lon'] - # ret['address']['geo_lat'] = location['lat'] - # - # ret['type'] = ret.pop('establishment_type') - # ret['subtypes'] = ret.pop('establishment_subtypes') - # - # return ret \ No newline at end of file diff --git a/apps/transfer/management/commands/transfer.py b/apps/transfer/management/commands/transfer.py index 7de18f5d..e9e52712 100644 --- a/apps/transfer/management/commands/transfer.py +++ b/apps/transfer/management/commands/transfer.py @@ -15,8 +15,9 @@ class Command(BaseCommand): 'subscriber', 'recipe', 'partner', - 'gallery', 'establishment', + 'gallery', + 'commercial' ] def handle(self, *args, **options): diff --git a/apps/transfer/models.py b/apps/transfer/models.py index f2a634bf..f6dd2dbc 100644 --- a/apps/transfer/models.py +++ b/apps/transfer/models.py @@ -788,3 +788,23 @@ class PageMetadata(MigrateMixin): class Meta: managed = False db_table = 'page_metadata' + + +class Ads(MigrateMixin): + using = 'legacy' + + site_id = models.IntegerField(blank=True, null=True) + href = models.CharField(max_length=255, blank=True, null=True) + start_at = models.DateTimeField(blank=True, null=True) + expire_at = models.DateTimeField(blank=True, null=True) + attachment_file_name = models.CharField(max_length=255, blank=True, null=True) + attachment_content_type = models.CharField(max_length=255, blank=True, null=True) + attachment_file_size = models.IntegerField(blank=True, null=True) + attachment_updated_at = models.DateTimeField(blank=True, null=True) + geometries = models.CharField(max_length=1024, blank=True, null=True) + created_at = models.DateTimeField() + updated_at = models.DateTimeField() + + class Meta: + managed = False + db_table = 'ads' \ No newline at end of file diff --git a/apps/transfer/serializers/advertisement.py b/apps/transfer/serializers/advertisement.py new file mode 100644 index 00000000..2e3a488f --- /dev/null +++ b/apps/transfer/serializers/advertisement.py @@ -0,0 +1,39 @@ +from rest_framework import serializers +from advertisement.models import Advertisement +import yaml + + +class AdvertisementSerializer(serializers.ModelSerializer): + href = serializers.CharField() + geometries = serializers.CharField(max_length=1024) + + class Meta: + model = Advertisement + fields = ( + "href", + "geometries" + ) + + def validate(self, data): + data["url"] = data["href"] + data["width"] = self.get_width(data["geometries"]) + data["height"] = self.get_height(data["geometries"]) + data.pop("href") + data.pop("geometries") + return data + + def create(self, validated_data): + return Advertisement.objects.create(**validated_data) + + def get_width(self, data): + data = self.parse_geometries(data) + return int(float(data["width"])) + + def get_height(self, data): + data = self.parse_geometries(data) + return int(float(data["height"])) + + def parse_geometries(self, geo_str): + clear_str = "!ruby/object:Paperclip::Geometry" + content_dict = yaml.safe_load(geo_str.replace(clear_str, '')) + return content_dict[':original'] \ No newline at end of file diff --git a/apps/transfer/serializers/recipe.py b/apps/transfer/serializers/recipe.py index 890d2b42..3948bbdd 100644 --- a/apps/transfer/serializers/recipe.py +++ b/apps/transfer/serializers/recipe.py @@ -1,8 +1,10 @@ from rest_framework import serializers from recipe.models import Recipe +from utils.legacy_parser import parse_legacy_content class RecipeSerializer(serializers.ModelSerializer): + locale = serializers.CharField() body = serializers.CharField(allow_null=True) title = serializers.CharField() state = serializers.CharField() @@ -14,7 +16,8 @@ class RecipeSerializer(serializers.ModelSerializer): "body", "title", "state", - "created_at" + "created_at", + 'locale', ) def validate(self, data): @@ -22,6 +25,7 @@ class RecipeSerializer(serializers.ModelSerializer): data["title"] = self.get_title(data) data["description"] = self.get_description(data) data.pop("body") + data.pop("locale") return data def create(self, validated_data): @@ -38,9 +42,14 @@ class RecipeSerializer(serializers.ModelSerializer): return Recipe.WAITING def get_title(self, obj): - tit = obj.get("title") - return {"en-GB": tit} + # tit = obj.get("title") + # return {"en-GB": tit} + return {obj['locale']: obj['title']} def get_description(self, obj): - desc = obj.get("body") - return {"en-GB": desc} + # desc = obj.get("body") + # return {"en-GB": desc} + content = None + if obj['body']: + content = parse_legacy_content(obj['body']) + return {obj['locale']: content} diff --git a/apps/utils/serializers.py b/apps/utils/serializers.py index 90efea00..eeff1043 100644 --- a/apps/utils/serializers.py +++ b/apps/utils/serializers.py @@ -1,4 +1,5 @@ """Utils app serializer.""" +import pytz from django.core import exceptions from rest_framework import serializers from utils import models @@ -48,6 +49,25 @@ class TJSONField(serializers.JSONField): validators = [validate_tjson] +class TimeZoneChoiceField(serializers.ChoiceField): + """Take the timezone object and make it JSON serializable.""" + + def __init__(self, choices=None, **kwargs): + if choices is None: + choices = pytz.all_timezones + super().__init__(choices=choices, **kwargs) + + def to_representation(self, value): + if isinstance(value, str): + return value + elif isinstance(value, pytz.tzinfo.BaseTzInfo): + return value.zone + return None + + def to_internal_value(self, data): + return pytz.timezone(data) + + class ProjectModelSerializer(serializers.ModelSerializer): """Overrided ModelSerializer.""" diff --git a/apps/utils/tests/tests_translated.py b/apps/utils/tests/tests_translated.py index 7a304095..77b67d8a 100644 --- a/apps/utils/tests/tests_translated.py +++ b/apps/utils/tests/tests_translated.py @@ -27,7 +27,7 @@ class BaseTestCase(APITestCase): self.client.cookies = SimpleCookie( {'access_token': tokkens.get('access_token'), 'refresh_token': tokkens.get('refresh_token'), - 'locale': "en" + 'locale': "en-GB" }) @@ -58,12 +58,11 @@ class TranslateFieldTests(BaseTestCase): def test_model_field(self): self.assertTrue(hasattr(self.news_item, "title_translated")) - def test_read_locale(self): response = self.client.get(f"/api/web/news/slug/{self.news_item.slug}/", format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) news_data = response.json() - + print(news_data) self.assertIn("title_translated", news_data) self.assertIn("Test news item", news_data['title_translated']) diff --git a/docker-compose.yml b/docker-compose.yml index 3b446101..c518a3ad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,14 +31,6 @@ services: # Redis redis: image: redis:2.8.23 - ports: - - "6379:6379" - - # RabbitMQ - #rabbitmq: - # image: rabbitmq:latest - # ports: - # - "5672:5672" # Celery worker: diff --git a/project/settings/base.py b/project/settings/base.py index f2001779..676a67d1 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -159,8 +159,9 @@ DATABASES = { }, 'legacy': { 'ENGINE': 'django.db.backends.mysql', + 'HOST': '172.17.0.1', # 'HOST': '172.23.0.1', - 'HOST': 'mysql_db', + # 'HOST': 'mysql_db', 'PORT': 3306, 'NAME': 'dev', 'USER': 'dev', @@ -482,4 +483,4 @@ STATICFILES_DIRS = ( # MEDIA -MEDIA_LOCATION = 'media' \ No newline at end of file +MEDIA_LOCATION = 'media' diff --git a/project/settings/development.py b/project/settings/development.py index 3e9968f4..73e0095d 100644 --- a/project/settings/development.py +++ b/project/settings/development.py @@ -19,7 +19,8 @@ DOMAIN_URI = 'gm.id-east.ru' # ELASTICSEARCH SETTINGS ELASTICSEARCH_DSL = { 'default': { - 'hosts': 'elasticsearch:9200' + 'hosts': 'localhost:9200' + # 'hosts': 'elasticsearch:9200' } } @@ -34,3 +35,7 @@ sentry_sdk.init( dsn="https://35d9bb789677410ab84a822831c6314f@sentry.io/1729093", integrations=[DjangoIntegration()] ) + +# TMP ( TODO remove it later) +# Временный хардкод для демонстрации 4 ноября, потом удалить! +HARDCODED_INTERNATIONAL_NEWS_IDS = [8, 9, 10, 11, 15, 17] diff --git a/project/settings/stage.py b/project/settings/stage.py index 49a7ae0f..0afe7e4e 100644 --- a/project/settings/stage.py +++ b/project/settings/stage.py @@ -26,3 +26,8 @@ ELASTICSEARCH_INDEX_NAMES = { # 'search_indexes.documents.news': 'stage_news', #temporarily disabled 'search_indexes.documents.establishment': 'stage_establishment', } + + +# TMP ( TODO remove it later) +# Временный хардкод для демонстрации 4 ноября, потом удалить! +HARDCODED_INTERNATIONAL_NEWS_IDS = [8, 9, 10, 11, 15, 17] \ No newline at end of file