diff --git a/apps/establishment/admin.py b/apps/establishment/admin.py index 62b8a8da..95ee81e2 100644 --- a/apps/establishment/admin.py +++ b/apps/establishment/admin.py @@ -87,3 +87,8 @@ class MenuAdmin(BaseModelAdminMixin, admin.ModelAdmin): return obj.category_translated category_translated.short_description = _('category') + + +@admin.register(models.RatingStrategy) +class RatingStrategyAdmin(BaseModelAdminMixin, admin.ModelAdmin): + """Admin conf for Rating Strategy model.""" diff --git a/apps/establishment/management/commands/add_establishment_mark.py b/apps/establishment/management/commands/add_establishment_mark.py index 1588268f..11053339 100644 --- a/apps/establishment/management/commands/add_establishment_mark.py +++ b/apps/establishment/management/commands/add_establishment_mark.py @@ -1,5 +1,3 @@ -from pprint import pprint - from django.core.management.base import BaseCommand from django.db.models import Q @@ -19,8 +17,6 @@ class Command(BaseCommand): Q(mark__isnull=True) ).filter(aasm_state='published').values_list('establishment_id', 'mark', 'updated_at') - print(queryset.count()) - for es_id, new_mark, new_date in queryset: try: mark, date = valid_data[es_id] @@ -41,6 +37,5 @@ class Command(BaseCommand): establishment.public_mark = int(value[0]) establishment.save() count += 1 - break self.stdout.write(self.style.WARNING(f'Updated {count} objects.')) diff --git a/apps/establishment/management/commands/recalculate_toque_number.py b/apps/establishment/management/commands/recalculate_toque_number.py new file mode 100644 index 00000000..00e6eb69 --- /dev/null +++ b/apps/establishment/management/commands/recalculate_toque_number.py @@ -0,0 +1,16 @@ +"""Run recalculating toque number for establishments.""" +from django.core.management.base import BaseCommand +from establishment.models import Establishment + + +class Command(BaseCommand): + + help = 'Recalculation toque number for all establishments.' + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def handle(self, *args, **options): + for establishment in Establishment.objects.select_related('address__city__country'): + print(f'Recalculate for {establishment.name} ({establishment.id})') + establishment.recalculate_toque_number() diff --git a/apps/establishment/migrations/0048_ratingstrategy.py b/apps/establishment/migrations/0048_ratingstrategy.py new file mode 100644 index 00000000..06cbc9ee --- /dev/null +++ b/apps/establishment/migrations/0048_ratingstrategy.py @@ -0,0 +1,33 @@ +# Generated by Django 2.2.4 on 2019-10-31 15:55 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('location', '0020_merge_20191030_1714'), + ('establishment', '0047_merge_20191030_1714'), + ] + + operations = [ + migrations.CreateModel( + name='RatingStrategy', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')), + ('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('toque_number', models.IntegerField(choices=[(1, 'One'), (2, 'Two'), (3, 'Three'), (4, 'Four'), (5, 'Five')])), + ('public_mark_min_value', models.IntegerField()), + ('public_mark_max_value', models.IntegerField()), + ('country', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='location.Country', verbose_name='Country')), + ], + options={ + 'verbose_name': 'Rating strategy', + 'verbose_name_plural': 'Rating strategy', + 'unique_together': {('country', 'toque_number')}, + }, + ), + ] diff --git a/apps/establishment/migrations/0049_auto_20191031_1616.py b/apps/establishment/migrations/0049_auto_20191031_1616.py new file mode 100644 index 00000000..aced02d9 --- /dev/null +++ b/apps/establishment/migrations/0049_auto_20191031_1616.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.4 on 2019-10-31 16:16 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0048_ratingstrategy'), + ] + + operations = [ + migrations.AlterField( + model_name='ratingstrategy', + name='country', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='location.Country', verbose_name='Country'), + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 981f9bb3..957333ac 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -14,7 +14,6 @@ from django.db.models import When, Case, F, ExpressionWrapper, Subquery, Q from django.utils import timezone from django.utils.translation import gettext_lazy as _ from phonenumber_field.modelfields import PhoneNumberField -from pytz import timezone as ptz from timezone_field import TimeZoneField from collection.models import Collection @@ -384,7 +383,13 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin): # todo: recalculate toque_number def recalculate_toque_number(self): - self.toque_number = 4 + toque_number = None + if self.address and self.public_mark: + toque_number = RatingStrategy.objects. \ + get_toque_number(country=self.address.city.country, + public_mark=self.public_mark) + self.toque_number = toque_number + self.save() def recalculate_price_level(self, low_price=None, high_price=None): if low_price is None or high_price is None: @@ -669,3 +674,62 @@ class SocialNetwork(models.Model): def __str__(self): return self.title + +class RatingStrategyManager(models.Manager): + """Extended manager for RatingStrategy.""" + + def get_toque_number(self, country, public_mark): + """Get toque number for country and public_mark.""" + qs = self.model.objects.by_country(country) + if not qs.exists(): + qs = self.model.objects.by_country(None) + obj = qs.for_public_mark(public_mark).first() + if obj: + return obj.toque_number + return None + + +class RatingStrategyQuerySet(models.QuerySet): + """Extended queryset for RatingStrategy.""" + + def by_country(self, country): + """Filter by country.""" + return self.filter(country=country) + + def for_public_mark(self, public_mark): + """Filter for value.""" + return self.filter(public_mark_min_value__lte=public_mark, + public_mark_max_value__gte=public_mark) + + +class RatingStrategy(ProjectBaseMixin): + """Rating Strategy model.""" + + TOQUE_NUMBER_CHOICES = ( + (1, _('One')), + (2, _('Two')), + (3, _('Three')), + (4, _('Four')), + (5, _('Five')), + ) + + country = models.ForeignKey('location.Country', null=True, blank=True, + default=None, on_delete=models.CASCADE, + verbose_name=_('Country')) + toque_number = models.IntegerField(choices=TOQUE_NUMBER_CHOICES) + public_mark_min_value = models.IntegerField() + public_mark_max_value = models.IntegerField() + + objects = RatingStrategyManager.from_queryset(RatingStrategyQuerySet)() + + class Meta: + """Meta class.""" + + verbose_name = _('Rating strategy') + verbose_name_plural = _('Rating strategy') + unique_together = ('country', 'toque_number') + + def __str__(self): + return f'{self.country.code if self.country else "Other country"}. ' \ + f'"{self.toque_number}": {self.public_mark_min_value}-' \ + f'{self.public_mark_max_value}' \ No newline at end of file diff --git a/apps/location/transfer_data.py b/apps/location/transfer_data.py index afd964ee..47d72c72 100644 --- a/apps/location/transfer_data.py +++ b/apps/location/transfer_data.py @@ -1,6 +1,8 @@ from django.db.models import Q, QuerySet -from transfer.serializers.location import CountrySerializer, RegionSerializer, CitySerializer, AddressSerializer +from transfer.serializers.location import CountrySerializer, RegionSerializer, \ + CitySerializer, AddressSerializer, \ + Country from transfer.models import Cities, Locations from pprint import pprint @@ -131,6 +133,13 @@ def transfer_addresses(): pprint(f"Address serializer errors: {serialized_data.errors}") +def update_flags(): + queryset = Country.objects.only("id", "code", "svg_image").filter(old_id__isnull=False) + + for query in queryset: + query.svg_image = f"/image/image/10-31-2019/{query.code}.svg" + query.save() + data_types = { "dictionaries": [ @@ -138,5 +147,8 @@ data_types = { transfer_regions, transfer_cities, transfer_addresses + ], + "update_country_flag": [ + update_flags ] } diff --git a/apps/main/migrations/0024_auto_20191031_1439.py b/apps/main/migrations/0024_auto_20191031_1439.py new file mode 100644 index 00000000..304c83fe --- /dev/null +++ b/apps/main/migrations/0024_auto_20191031_1439.py @@ -0,0 +1,48 @@ +# Generated by Django 2.2.4 on 2019-10-31 14:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0023_merge_20191028_0725'), + ] + + operations = [ + migrations.AddField( + model_name='carousel', + name='active', + field=models.BooleanField(default=False, verbose_name='old active'), + ), + migrations.AddField( + model_name='carousel', + name='attachment_suffix_url', + field=models.TextField(blank=True, default=None, null=True, verbose_name='old attachment_suffix_url'), + ), + migrations.AddField( + model_name='carousel', + name='description', + field=models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='old description'), + ), + migrations.AddField( + model_name='carousel', + name='link', + field=models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='old link'), + ), + migrations.AddField( + model_name='carousel', + name='link_title', + field=models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='old link_title'), + ), + migrations.AddField( + model_name='carousel', + name='old_id', + field=models.PositiveIntegerField(blank=True, default=None, null=True, verbose_name='old id'), + ), + migrations.AddField( + model_name='carousel', + name='title', + field=models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='old title'), + ), + ] diff --git a/apps/main/migrations/0025_carousel_is_parse.py b/apps/main/migrations/0025_carousel_is_parse.py new file mode 100644 index 00000000..81ede657 --- /dev/null +++ b/apps/main/migrations/0025_carousel_is_parse.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.4 on 2019-10-31 15:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0024_auto_20191031_1439'), + ] + + operations = [ + migrations.AddField( + model_name='carousel', + name='is_parse', + field=models.BooleanField(default=False, verbose_name='is parse'), + ), + ] diff --git a/apps/main/migrations/0026_auto_20191101_0500.py b/apps/main/migrations/0026_auto_20191101_0500.py new file mode 100644 index 00000000..55ecaad0 --- /dev/null +++ b/apps/main/migrations/0026_auto_20191101_0500.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.4 on 2019-11-01 05:00 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0025_carousel_is_parse'), + ] + + operations = [ + migrations.AlterField( + model_name='carousel', + name='content_type', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'), + ), + migrations.AlterField( + model_name='carousel', + name='object_id', + field=models.PositiveIntegerField(blank=True, default=None, null=True), + ), + ] diff --git a/apps/main/models.py b/apps/main/models.py index 6af4e4d8..7dee5cf0 100644 --- a/apps/main/models.py +++ b/apps/main/models.py @@ -130,7 +130,6 @@ class SiteSettingsQuerySet(models.QuerySet): class SiteSettings(ProjectBaseMixin): - subdomain = models.CharField(max_length=255, db_index=True, unique=True, verbose_name=_('Subdomain')) country = models.OneToOneField(Country, on_delete=models.PROTECT, @@ -172,8 +171,9 @@ class SiteSettings(ProjectBaseMixin): @property def published_sitefeatures(self): - return self.sitefeature_set\ - .filter(Q(published=True) and Q(feature__source__in=[PlatformMixin.WEB, PlatformMixin.ALL])) + return self.sitefeature_set. \ + filter(Q(published=True) & + Q(feature__source__in=[PlatformMixin.WEB, PlatformMixin.ALL])) @property def site_url(self): @@ -281,10 +281,19 @@ class CarouselQuerySet(models.QuerySet): class Carousel(models.Model): """Carousel model.""" - content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) - object_id = models.PositiveIntegerField() + content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, blank=True, null=True, default=None) + object_id = models.PositiveIntegerField(blank=True, null=True, default=None) content_object = generic.GenericForeignKey('content_type', 'object_id') + old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None) + title = models.CharField(_('old title'), max_length=255, blank=True, null=True, default=None) + link = models.CharField(_('old link'), max_length=255, blank=True, null=True, default=None) + attachment_suffix_url = models.TextField(_('old attachment_suffix_url'), blank=True, null=True, default=None) + description = models.CharField(_('old description'), max_length=255, blank=True, null=True, default=None) + link_title = models.CharField(_('old link_title'), max_length=255, blank=True, null=True, default=None) + active = models.BooleanField(_('old active'), default=False) + is_parse = models.BooleanField(_('is parse'), default=False) + objects = CarouselQuerySet.as_manager() class Meta: diff --git a/apps/main/transfer.py b/apps/main/transfer.py index 5d9caafe..52bde4d9 100644 --- a/apps/main/transfer.py +++ b/apps/main/transfer.py @@ -71,7 +71,8 @@ card = { "facebook_page_url": "facebook_page_url", "instagram_page_url": "instagram_page_url", "contact_email": "contact_email", - "config": ("config", "django.db.models.JSONField") #TODO в качесте ключа использовать country_code_2 из legacy - ? + "config": ("config", "django.db.models.JSONField") + # TODO в качесте ключа использовать country_code_2 из legacy - ? }, # "relations": { # # Как работать c отношение OneToOneField @@ -133,7 +134,7 @@ card = { "vintage_year": "year", } }, - #TODO вопрос с content_type + # TODO вопрос с content_type "relations": { "AwardTypes": [( ("award_type", None), @@ -143,4 +144,4 @@ card = { } } -used_apps = ("locations", ) \ No newline at end of file +used_apps = ("locations",) diff --git a/apps/main/transfer_data.py b/apps/main/transfer_data.py new file mode 100644 index 00000000..efb7938d --- /dev/null +++ b/apps/main/transfer_data.py @@ -0,0 +1,19 @@ +from pprint import pprint + +from transfer.models import CarouselElements +from transfer.serializers.carousel import CarouselSerializer + + +def transfer_carousel(): + queryset = CarouselElements.objects.all() + + serialized_data = CarouselSerializer(data=list(queryset.values()), many=True) + if serialized_data.is_valid(): + serialized_data.save() + else: + pprint(f'Carousel serializer errors: {serialized_data.errors}') + + +data_types = { + 'whirligig': [transfer_carousel] +} diff --git a/apps/search_indexes/documents/establishment.py b/apps/search_indexes/documents/establishment.py index e4e0c937..7eac2d6c 100644 --- a/apps/search_indexes/documents/establishment.py +++ b/apps/search_indexes/documents/establishment.py @@ -37,7 +37,7 @@ class EstablishmentDocument(Document): works_noon = fields.ListField(fields.IntegerField( attr='works_noon' )) - # works_now = fields.BooleanField(attr='works_now') + works_now = fields.BooleanField(attr='works_now') tags = fields.ObjectField( properties={ 'id': fields.IntegerField(attr='id'), diff --git a/apps/search_indexes/filters.py b/apps/search_indexes/filters.py index f9ae0ef1..93208a71 100644 --- a/apps/search_indexes/filters.py +++ b/apps/search_indexes/filters.py @@ -1,7 +1,7 @@ """Search indexes filters.""" from elasticsearch_dsl.query import Q from django_elasticsearch_dsl_drf.filter_backends import SearchFilterBackend -from utils.models import get_current_language +from utils.models import get_current_locale class CustomSearchFilterBackend(SearchFilterBackend): @@ -12,7 +12,7 @@ class CustomSearchFilterBackend(SearchFilterBackend): field_name = field if hasattr(view, 'search_fields') and hasattr(view, 'translated_search_fields'): if field in view.translated_search_fields: - field_name = f'{field}.{get_current_language()}' + field_name = f'{field}.{get_current_locale()}' return field_name def construct_search(self, request, view): diff --git a/apps/search_indexes/utils.py b/apps/search_indexes/utils.py index 0c1dd187..d6153da2 100644 --- a/apps/search_indexes/utils.py +++ b/apps/search_indexes/utils.py @@ -1,6 +1,6 @@ """Search indexes utils.""" from django_elasticsearch_dsl import fields -from utils.models import get_current_language +from utils.models import get_current_locale, get_default_locale # object field properties @@ -19,4 +19,8 @@ def get_translated_value(value): field_dict = value.to_dict() elif isinstance(value, dict): field_dict = value - return field_dict.get(get_current_language()) + value = field_dict.get(get_current_locale()) + # fallback + if value is None: + value = field_dict.get(get_default_locale()) + return value diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index 1cbf9d05..a53e2615 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -139,7 +139,7 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet): 'lookups': [ constants.LOOKUP_QUERY_IN, ], - }, + }, 'works_noon': { 'field': 'works_noon', 'lookups': [ @@ -152,12 +152,12 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet): constants.LOOKUP_QUERY_IN, ], }, - # 'works_now': { - # 'field': 'works_now', - # 'lookups': [ - # constants.LOOKUP_FILTER_TERM, - # ] - # }, + 'works_now': { + 'field': 'works_now', + 'lookups': [ + constants.LOOKUP_FILTER_TERM, + ] + }, } geo_spatial_filter_fields = { diff --git a/apps/tag/serializers.py b/apps/tag/serializers.py index c09f42f1..f9bab992 100644 --- a/apps/tag/serializers.py +++ b/apps/tag/serializers.py @@ -14,7 +14,8 @@ class TagBaseSerializer(serializers.ModelSerializer): # todo: refactor this # label_translated = TranslatedField() - label_translated = serializers.CharField(source='value') + label_translated = serializers.CharField(source='value', read_only=True, allow_null=True) + index_name = serializers.CharField(source='value', read_only=True, allow_null=True) class Meta: """Meta class.""" @@ -23,6 +24,7 @@ class TagBaseSerializer(serializers.ModelSerializer): fields = ( 'id', 'label_translated', + 'index_name', ) @@ -43,7 +45,7 @@ class TagCategoryBaseSerializer(serializers.ModelSerializer): # todo: refactor this # label_translated = TranslatedField() - label_translated = serializers.CharField(source='index_name') + label_translated = serializers.CharField(source='index_name', read_only=True, allow_null=True) tags = TagBaseSerializer(many=True, read_only=True) class Meta: diff --git a/apps/transfer/management/commands/transfer.py b/apps/transfer/management/commands/transfer.py index f3abbfab..dcfcbea9 100644 --- a/apps/transfer/management/commands/transfer.py +++ b/apps/transfer/management/commands/transfer.py @@ -8,7 +8,7 @@ class Command(BaseCommand): """Типы данных для трансфера ВНИМАНИЕ: первые буквы типов данных должны быть уникальны! """ - DATA_TYPES = [ + SHORT_DATA_TYPES = [ 'dictionaries', 'news', 'account', @@ -21,20 +21,40 @@ class Command(BaseCommand): 'overlook', 'tmp', 'menu', - 'location_establishment' + 'location_establishment', + 'whirligig', + ] + + LONG_DATA_TYPES = [ + 'update_country_flag' ] def handle(self, *args, **options): """Находим включённую опцию путём пересечения множества типов данных и множества включённых опций""" - data_type = list(set(option for option in options.keys() if options[option]) & set(self.DATA_TYPES)) + data_type = list(set(option for option in options.keys() if options[option]) & set(self.LONG_DATA_TYPES)) if len(data_type) != 1: - print("You must set correct option!\r\nYou can get options list with \r\n\r\n\tmanage.py help transfer\r\n") - exit(1) - transfer_objects(data_type[0]) + data_type = list(set(option for option in options.keys() if options[option]) & set(self.SHORT_DATA_TYPES)) + if len(data_type) != 1: + print("You must set correct option!\r\nYou can get options list with \r\n\r\n\tmanage.py help transfer\r\n") + exit(1) + else: + data_type = data_type[0] + else: + data_type = data_type[0] + + transfer_objects(data_type) def add_arguments(self, parser): + for option_type in self.LONG_DATA_TYPES: + parser.add_argument( + f'--{option_type}', + action='store_true', + default=False, + help=f'Transfer {option_type} objects' + ) + """Добавляем опции к команде, основываясь на типах данных, определённых в DATA_TYPES""" - for option_type in self.DATA_TYPES: + for option_type in self.SHORT_DATA_TYPES: parser.add_argument( f'-{option_type[:1]}', f'--{option_type}', diff --git a/apps/transfer/models.py b/apps/transfer/models.py index ccda8cd6..d81479a7 100644 --- a/apps/transfer/models.py +++ b/apps/transfer/models.py @@ -938,3 +938,25 @@ class KeyValueMetadatumKeyValueMetadatumEstablishments(MigrateMixin): # class Meta: # managed = False # db_table = 'wine_types' + +class CarouselElements(MigrateMixin): + using = 'legacy' + + title = models.CharField(max_length=255, blank=True, null=True) + link = models.CharField(max_length=255, blank=True, null=True) + home_page_id = models.IntegerField(blank=True, null=True) + created_at = models.DateTimeField() + updated_at = models.DateTimeField() + 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) + attachment_suffix_url = models.TextField(blank=True, null=True) + geometries = models.CharField(max_length=1024, blank=True, null=True) + active = models.IntegerField(blank=True, null=True) + description = models.CharField(max_length=255, blank=True, null=True) + link_title = models.CharField(max_length=255, blank=True, null=True) + + class Meta: + managed = False + db_table = 'carousel_elements' diff --git a/apps/transfer/serializers/carousel.py b/apps/transfer/serializers/carousel.py new file mode 100644 index 00000000..3f1e8ecb --- /dev/null +++ b/apps/transfer/serializers/carousel.py @@ -0,0 +1,59 @@ +from django.contrib.contenttypes.models import ContentType +from rest_framework import serializers + +from establishment.models import Establishment +from main.models import Carousel +from news.models import News + + +def get_obj_data(model, slug): + try: + obj = model.objects.get(slug=slug) + except model.DoesNotExist: + return None, None + else: + content_type = ContentType.objects.get_for_model(obj) + return obj.id, content_type.id + + +class CarouselSerializer(serializers.Serializer): + id = serializers.IntegerField() + title = serializers.CharField(allow_null=True, allow_blank=True) + link = serializers.CharField(allow_null=True) + link_title = serializers.CharField(allow_null=True, allow_blank=True) + description = serializers.CharField(allow_null=True, allow_blank=True) + attachment_suffix_url = serializers.CharField(allow_null=True) + active = serializers.IntegerField() + + def create(self, validated_data): + object_id, content_type_id = self.get_content_type(validated_data) + validated_data.update({ + 'active': bool(int(validated_data['active'])), + 'content_type_id': content_type_id, + 'object_id': object_id, + 'is_parse': bool(object_id), + }) + obj = Carousel.objects.create(**validated_data) + return obj + + @staticmethod + def get_content_type(data): + link = data['link'] + if not link: + return None + + obj_data = None, None + site = 'gaultmillau.com' + if site in link: + data = link.split('/') + + try: + _type = data[3] + except IndexError: + pass + else: + if _type in ('news', 'pages'): + obj_data = get_obj_data(News, data[4]) + elif _type == 'restaurant': + obj_data = get_obj_data(Establishment, data[4]) + return obj_data diff --git a/apps/transfer/serializers/establishment.py b/apps/transfer/serializers/establishment.py index 7c8ce97c..6a2fcde5 100644 --- a/apps/transfer/serializers/establishment.py +++ b/apps/transfer/serializers/establishment.py @@ -6,8 +6,8 @@ from establishment.models import Establishment, ContactEmail, ContactPhone, Esta from location.models import Address from timetable.models import Timetable from utils.legacy_parser import parse_legacy_schedule_content +from utils.serializers import TimeZoneChoiceField from utils.slug_generator import generate_unique_slug -from pytz import timezone as ptz class EstablishmentSerializer(serializers.ModelSerializer): @@ -26,7 +26,7 @@ class EstablishmentSerializer(serializers.ModelSerializer): twitter = serializers.CharField(allow_null=True, allow_blank=True) booking = serializers.CharField(allow_null=True, allow_blank=True) state = serializers.CharField(allow_null=True) - tz = serializers.CharField() + tz = TimeZoneChoiceField() created = serializers.DateTimeField(format='%m-%d-%Y %H:%M:%S') class Meta: @@ -59,7 +59,6 @@ class EstablishmentSerializer(serializers.ModelSerializer): 'establishment_type_id': self.get_type(data), 'is_publish': data.get('state') == 'published', }) - data['tz'] = ptz(data['tz']) data.pop('location') data.pop('type') data.pop('state') diff --git a/apps/transfer/utils.py b/apps/transfer/utils.py index b83d5b2b..eb8b3336 100644 --- a/apps/transfer/utils.py +++ b/apps/transfer/utils.py @@ -8,7 +8,9 @@ def transfer_objects(data_type): for app in apps.get_app_configs(): if exists(f"{app.path}/transfer_data.py"): card_module = SourceFileLoader("transfer", f"{app.path}/transfer_data.py").load_module() - if not hasattr(card_module, "data_types") or not isinstance(card_module.data_types, dict) or len(card_module.data_types) < 1: + if not hasattr(card_module, "data_types") \ + or not isinstance(card_module.data_types, dict) \ + or len(card_module.data_types) < 1: continue for module_data_type, transfer_funcs in card_module.data_types.items(): diff --git a/apps/utils/models.py b/apps/utils/models.py index 0c94d23f..55512e88 100644 --- a/apps/utils/models.py +++ b/apps/utils/models.py @@ -10,6 +10,7 @@ from django.contrib.postgres.fields.jsonb import KeyTextTransform from django.utils import timezone from django.utils.html import mark_safe from django.utils.translation import ugettext_lazy as _, get_language +from configuration.models import TranslationSettings from easy_thumbnails.fields import ThumbnailerImageField from sorl.thumbnail import get_thumbnail from sorl.thumbnail.fields import ImageField as SORLImageField @@ -59,13 +60,26 @@ def to_locale(language): return language + '-' + country +def get_current_locale(): + """Get current language.""" + return to_locale(get_language()) + + +def get_default_locale(): + return TranslationSettings.get_solo().default_language or \ + settings.FALLBACK_LOCALE + + def translate_field(self, field_name): def translate(self): field = getattr(self, field_name) if isinstance(field, dict): - return field.get(to_locale(get_language())) + value = field.get(to_locale(get_language())) + # fallback + if value is None: + value = field.get(get_default_locale()) + return value return None - return translate @@ -111,15 +125,10 @@ class TranslatedFieldsMixin: if self.STR_FIELD_NAME: field = getattr(self, getattr(self, 'STR_FIELD_NAME')) if isinstance(field, dict): - value = field.get(get_current_language()) + value = field.get(get_current_locale()) return value if value else super(TranslatedFieldsMixin, self).__str__() -def get_current_language(): - """Get current language.""" - return to_locale(get_language()) - - class OAuthProjectMixin: """OAuth2 mixin for project GM""" diff --git a/project/settings/base.py b/project/settings/base.py index d2cf7b49..c08a7d0d 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -159,9 +159,9 @@ DATABASES = { }, 'legacy': { 'ENGINE': 'django.db.backends.mysql', - 'HOST': '172.17.0.1', + # 'HOST': '172.17.0.1', # 'HOST': '172.23.0.1', - # 'HOST': 'mysql_db', + 'HOST': 'mysql_db', 'PORT': 3306, 'NAME': 'dev', 'USER': 'dev', @@ -488,3 +488,5 @@ MEDIA_LOCATION = 'media' PHONENUMBER_DB_FORMAT = 'NATIONAL' PHONENUMBER_DEFAULT_REGION = "FR" + +FALLBACK_LOCALE = 'en-GB'