Merge branch 'develop' into feature/collect
This commit is contained in:
commit
954d515a5a
|
|
@ -87,3 +87,8 @@ class MenuAdmin(BaseModelAdminMixin, admin.ModelAdmin):
|
||||||
return obj.category_translated
|
return obj.category_translated
|
||||||
|
|
||||||
category_translated.short_description = _('category')
|
category_translated.short_description = _('category')
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(models.RatingStrategy)
|
||||||
|
class RatingStrategyAdmin(BaseModelAdminMixin, admin.ModelAdmin):
|
||||||
|
"""Admin conf for Rating Strategy model."""
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
from pprint import pprint
|
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
|
|
@ -19,8 +17,6 @@ class Command(BaseCommand):
|
||||||
Q(mark__isnull=True)
|
Q(mark__isnull=True)
|
||||||
).filter(aasm_state='published').values_list('establishment_id', 'mark', 'updated_at')
|
).filter(aasm_state='published').values_list('establishment_id', 'mark', 'updated_at')
|
||||||
|
|
||||||
print(queryset.count())
|
|
||||||
|
|
||||||
for es_id, new_mark, new_date in queryset:
|
for es_id, new_mark, new_date in queryset:
|
||||||
try:
|
try:
|
||||||
mark, date = valid_data[es_id]
|
mark, date = valid_data[es_id]
|
||||||
|
|
@ -41,6 +37,5 @@ class Command(BaseCommand):
|
||||||
establishment.public_mark = int(value[0])
|
establishment.public_mark = int(value[0])
|
||||||
establishment.save()
|
establishment.save()
|
||||||
count += 1
|
count += 1
|
||||||
break
|
|
||||||
|
|
||||||
self.stdout.write(self.style.WARNING(f'Updated {count} objects.'))
|
self.stdout.write(self.style.WARNING(f'Updated {count} objects.'))
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
33
apps/establishment/migrations/0048_ratingstrategy.py
Normal file
33
apps/establishment/migrations/0048_ratingstrategy.py
Normal file
|
|
@ -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')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
19
apps/establishment/migrations/0049_auto_20191031_1616.py
Normal file
19
apps/establishment/migrations/0049_auto_20191031_1616.py
Normal file
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -14,7 +14,6 @@ from django.db.models import When, Case, F, ExpressionWrapper, Subquery, Q
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from phonenumber_field.modelfields import PhoneNumberField
|
from phonenumber_field.modelfields import PhoneNumberField
|
||||||
from pytz import timezone as ptz
|
|
||||||
from timezone_field import TimeZoneField
|
from timezone_field import TimeZoneField
|
||||||
|
|
||||||
from collection.models import Collection
|
from collection.models import Collection
|
||||||
|
|
@ -384,7 +383,13 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
||||||
|
|
||||||
# todo: recalculate toque_number
|
# todo: recalculate toque_number
|
||||||
def recalculate_toque_number(self):
|
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):
|
def recalculate_price_level(self, low_price=None, high_price=None):
|
||||||
if low_price is None or high_price is None:
|
if low_price is None or high_price is None:
|
||||||
|
|
@ -669,3 +674,62 @@ class SocialNetwork(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
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}'
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
from django.db.models import Q, QuerySet
|
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 transfer.models import Cities, Locations
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
@ -131,6 +133,13 @@ def transfer_addresses():
|
||||||
pprint(f"Address serializer errors: {serialized_data.errors}")
|
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 = {
|
data_types = {
|
||||||
"dictionaries": [
|
"dictionaries": [
|
||||||
|
|
@ -138,5 +147,8 @@ data_types = {
|
||||||
transfer_regions,
|
transfer_regions,
|
||||||
transfer_cities,
|
transfer_cities,
|
||||||
transfer_addresses
|
transfer_addresses
|
||||||
|
],
|
||||||
|
"update_country_flag": [
|
||||||
|
update_flags
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
48
apps/main/migrations/0024_auto_20191031_1439.py
Normal file
48
apps/main/migrations/0024_auto_20191031_1439.py
Normal file
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
18
apps/main/migrations/0025_carousel_is_parse.py
Normal file
18
apps/main/migrations/0025_carousel_is_parse.py
Normal file
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
24
apps/main/migrations/0026_auto_20191101_0500.py
Normal file
24
apps/main/migrations/0026_auto_20191101_0500.py
Normal file
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -130,7 +130,6 @@ class SiteSettingsQuerySet(models.QuerySet):
|
||||||
|
|
||||||
|
|
||||||
class SiteSettings(ProjectBaseMixin):
|
class SiteSettings(ProjectBaseMixin):
|
||||||
|
|
||||||
subdomain = models.CharField(max_length=255, db_index=True, unique=True,
|
subdomain = models.CharField(max_length=255, db_index=True, unique=True,
|
||||||
verbose_name=_('Subdomain'))
|
verbose_name=_('Subdomain'))
|
||||||
country = models.OneToOneField(Country, on_delete=models.PROTECT,
|
country = models.OneToOneField(Country, on_delete=models.PROTECT,
|
||||||
|
|
@ -172,8 +171,9 @@ class SiteSettings(ProjectBaseMixin):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def published_sitefeatures(self):
|
def published_sitefeatures(self):
|
||||||
return self.sitefeature_set\
|
return self.sitefeature_set. \
|
||||||
.filter(Q(published=True) and Q(feature__source__in=[PlatformMixin.WEB, PlatformMixin.ALL]))
|
filter(Q(published=True) &
|
||||||
|
Q(feature__source__in=[PlatformMixin.WEB, PlatformMixin.ALL]))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def site_url(self):
|
def site_url(self):
|
||||||
|
|
@ -281,10 +281,19 @@ class CarouselQuerySet(models.QuerySet):
|
||||||
|
|
||||||
class Carousel(models.Model):
|
class Carousel(models.Model):
|
||||||
"""Carousel model."""
|
"""Carousel model."""
|
||||||
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, blank=True, null=True, default=None)
|
||||||
object_id = models.PositiveIntegerField()
|
object_id = models.PositiveIntegerField(blank=True, null=True, default=None)
|
||||||
content_object = generic.GenericForeignKey('content_type', 'object_id')
|
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()
|
objects = CarouselQuerySet.as_manager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ card = {
|
||||||
"facebook_page_url": "facebook_page_url",
|
"facebook_page_url": "facebook_page_url",
|
||||||
"instagram_page_url": "instagram_page_url",
|
"instagram_page_url": "instagram_page_url",
|
||||||
"contact_email": "contact_email",
|
"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": {
|
# "relations": {
|
||||||
# # Как работать c отношение OneToOneField
|
# # Как работать c отношение OneToOneField
|
||||||
|
|
|
||||||
19
apps/main/transfer_data.py
Normal file
19
apps/main/transfer_data.py
Normal file
|
|
@ -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]
|
||||||
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ class EstablishmentDocument(Document):
|
||||||
works_noon = fields.ListField(fields.IntegerField(
|
works_noon = fields.ListField(fields.IntegerField(
|
||||||
attr='works_noon'
|
attr='works_noon'
|
||||||
))
|
))
|
||||||
# works_now = fields.BooleanField(attr='works_now')
|
works_now = fields.BooleanField(attr='works_now')
|
||||||
tags = fields.ObjectField(
|
tags = fields.ObjectField(
|
||||||
properties={
|
properties={
|
||||||
'id': fields.IntegerField(attr='id'),
|
'id': fields.IntegerField(attr='id'),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"""Search indexes filters."""
|
"""Search indexes filters."""
|
||||||
from elasticsearch_dsl.query import Q
|
from elasticsearch_dsl.query import Q
|
||||||
from django_elasticsearch_dsl_drf.filter_backends import SearchFilterBackend
|
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):
|
class CustomSearchFilterBackend(SearchFilterBackend):
|
||||||
|
|
@ -12,7 +12,7 @@ class CustomSearchFilterBackend(SearchFilterBackend):
|
||||||
field_name = field
|
field_name = field
|
||||||
if hasattr(view, 'search_fields') and hasattr(view, 'translated_search_fields'):
|
if hasattr(view, 'search_fields') and hasattr(view, 'translated_search_fields'):
|
||||||
if field in 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
|
return field_name
|
||||||
|
|
||||||
def construct_search(self, request, view):
|
def construct_search(self, request, view):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"""Search indexes utils."""
|
"""Search indexes utils."""
|
||||||
from django_elasticsearch_dsl import fields
|
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
|
# object field properties
|
||||||
|
|
@ -19,4 +19,8 @@ def get_translated_value(value):
|
||||||
field_dict = value.to_dict()
|
field_dict = value.to_dict()
|
||||||
elif isinstance(value, dict):
|
elif isinstance(value, dict):
|
||||||
field_dict = value
|
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
|
||||||
|
|
|
||||||
|
|
@ -152,12 +152,12 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
||||||
constants.LOOKUP_QUERY_IN,
|
constants.LOOKUP_QUERY_IN,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
# 'works_now': {
|
'works_now': {
|
||||||
# 'field': 'works_now',
|
'field': 'works_now',
|
||||||
# 'lookups': [
|
'lookups': [
|
||||||
# constants.LOOKUP_FILTER_TERM,
|
constants.LOOKUP_FILTER_TERM,
|
||||||
# ]
|
]
|
||||||
# },
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
geo_spatial_filter_fields = {
|
geo_spatial_filter_fields = {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ class TagBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
# todo: refactor this
|
# todo: refactor this
|
||||||
# label_translated = TranslatedField()
|
# 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:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
@ -23,6 +24,7 @@ class TagBaseSerializer(serializers.ModelSerializer):
|
||||||
fields = (
|
fields = (
|
||||||
'id',
|
'id',
|
||||||
'label_translated',
|
'label_translated',
|
||||||
|
'index_name',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -43,7 +45,7 @@ class TagCategoryBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
# todo: refactor this
|
# todo: refactor this
|
||||||
# label_translated = TranslatedField()
|
# 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)
|
tags = TagBaseSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ class Command(BaseCommand):
|
||||||
"""Типы данных для трансфера
|
"""Типы данных для трансфера
|
||||||
ВНИМАНИЕ: первые буквы типов данных должны быть уникальны!
|
ВНИМАНИЕ: первые буквы типов данных должны быть уникальны!
|
||||||
"""
|
"""
|
||||||
DATA_TYPES = [
|
SHORT_DATA_TYPES = [
|
||||||
'dictionaries',
|
'dictionaries',
|
||||||
'news',
|
'news',
|
||||||
'account',
|
'account',
|
||||||
|
|
@ -21,20 +21,40 @@ class Command(BaseCommand):
|
||||||
'overlook',
|
'overlook',
|
||||||
'tmp',
|
'tmp',
|
||||||
'menu',
|
'menu',
|
||||||
'location_establishment'
|
'location_establishment',
|
||||||
|
'whirligig',
|
||||||
|
]
|
||||||
|
|
||||||
|
LONG_DATA_TYPES = [
|
||||||
|
'update_country_flag'
|
||||||
]
|
]
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
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:
|
||||||
|
data_type = list(set(option for option in options.keys() if options[option]) & set(self.SHORT_DATA_TYPES))
|
||||||
if len(data_type) != 1:
|
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")
|
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)
|
exit(1)
|
||||||
transfer_objects(data_type[0])
|
else:
|
||||||
|
data_type = data_type[0]
|
||||||
|
else:
|
||||||
|
data_type = data_type[0]
|
||||||
|
|
||||||
|
transfer_objects(data_type)
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
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"""
|
"""Добавляем опции к команде, основываясь на типах данных, определённых в DATA_TYPES"""
|
||||||
for option_type in self.DATA_TYPES:
|
for option_type in self.SHORT_DATA_TYPES:
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
f'-{option_type[:1]}',
|
f'-{option_type[:1]}',
|
||||||
f'--{option_type}',
|
f'--{option_type}',
|
||||||
|
|
|
||||||
|
|
@ -938,3 +938,25 @@ class KeyValueMetadatumKeyValueMetadatumEstablishments(MigrateMixin):
|
||||||
# class Meta:
|
# class Meta:
|
||||||
# managed = False
|
# managed = False
|
||||||
# db_table = 'wine_types'
|
# 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'
|
||||||
|
|
|
||||||
59
apps/transfer/serializers/carousel.py
Normal file
59
apps/transfer/serializers/carousel.py
Normal file
|
|
@ -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
|
||||||
|
|
@ -6,8 +6,8 @@ from establishment.models import Establishment, ContactEmail, ContactPhone, Esta
|
||||||
from location.models import Address
|
from location.models import Address
|
||||||
from timetable.models import Timetable
|
from timetable.models import Timetable
|
||||||
from utils.legacy_parser import parse_legacy_schedule_content
|
from utils.legacy_parser import parse_legacy_schedule_content
|
||||||
|
from utils.serializers import TimeZoneChoiceField
|
||||||
from utils.slug_generator import generate_unique_slug
|
from utils.slug_generator import generate_unique_slug
|
||||||
from pytz import timezone as ptz
|
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentSerializer(serializers.ModelSerializer):
|
class EstablishmentSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -26,7 +26,7 @@ class EstablishmentSerializer(serializers.ModelSerializer):
|
||||||
twitter = serializers.CharField(allow_null=True, allow_blank=True)
|
twitter = serializers.CharField(allow_null=True, allow_blank=True)
|
||||||
booking = serializers.CharField(allow_null=True, allow_blank=True)
|
booking = serializers.CharField(allow_null=True, allow_blank=True)
|
||||||
state = serializers.CharField(allow_null=True)
|
state = serializers.CharField(allow_null=True)
|
||||||
tz = serializers.CharField()
|
tz = TimeZoneChoiceField()
|
||||||
created = serializers.DateTimeField(format='%m-%d-%Y %H:%M:%S')
|
created = serializers.DateTimeField(format='%m-%d-%Y %H:%M:%S')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -59,7 +59,6 @@ class EstablishmentSerializer(serializers.ModelSerializer):
|
||||||
'establishment_type_id': self.get_type(data),
|
'establishment_type_id': self.get_type(data),
|
||||||
'is_publish': data.get('state') == 'published',
|
'is_publish': data.get('state') == 'published',
|
||||||
})
|
})
|
||||||
data['tz'] = ptz(data['tz'])
|
|
||||||
data.pop('location')
|
data.pop('location')
|
||||||
data.pop('type')
|
data.pop('type')
|
||||||
data.pop('state')
|
data.pop('state')
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,9 @@ def transfer_objects(data_type):
|
||||||
for app in apps.get_app_configs():
|
for app in apps.get_app_configs():
|
||||||
if exists(f"{app.path}/transfer_data.py"):
|
if exists(f"{app.path}/transfer_data.py"):
|
||||||
card_module = SourceFileLoader("transfer", f"{app.path}/transfer_data.py").load_module()
|
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
|
continue
|
||||||
|
|
||||||
for module_data_type, transfer_funcs in card_module.data_types.items():
|
for module_data_type, transfer_funcs in card_module.data_types.items():
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ from django.contrib.postgres.fields.jsonb import KeyTextTransform
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.html import mark_safe
|
from django.utils.html import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _, get_language
|
from django.utils.translation import ugettext_lazy as _, get_language
|
||||||
|
from configuration.models import TranslationSettings
|
||||||
from easy_thumbnails.fields import ThumbnailerImageField
|
from easy_thumbnails.fields import ThumbnailerImageField
|
||||||
from sorl.thumbnail import get_thumbnail
|
from sorl.thumbnail import get_thumbnail
|
||||||
from sorl.thumbnail.fields import ImageField as SORLImageField
|
from sorl.thumbnail.fields import ImageField as SORLImageField
|
||||||
|
|
@ -59,13 +60,26 @@ def to_locale(language):
|
||||||
return language + '-' + country
|
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_field(self, field_name):
|
||||||
def translate(self):
|
def translate(self):
|
||||||
field = getattr(self, field_name)
|
field = getattr(self, field_name)
|
||||||
if isinstance(field, dict):
|
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 None
|
||||||
|
|
||||||
return translate
|
return translate
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -111,15 +125,10 @@ class TranslatedFieldsMixin:
|
||||||
if self.STR_FIELD_NAME:
|
if self.STR_FIELD_NAME:
|
||||||
field = getattr(self, getattr(self, 'STR_FIELD_NAME'))
|
field = getattr(self, getattr(self, 'STR_FIELD_NAME'))
|
||||||
if isinstance(field, dict):
|
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__()
|
return value if value else super(TranslatedFieldsMixin, self).__str__()
|
||||||
|
|
||||||
|
|
||||||
def get_current_language():
|
|
||||||
"""Get current language."""
|
|
||||||
return to_locale(get_language())
|
|
||||||
|
|
||||||
|
|
||||||
class OAuthProjectMixin:
|
class OAuthProjectMixin:
|
||||||
"""OAuth2 mixin for project GM"""
|
"""OAuth2 mixin for project GM"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -159,9 +159,9 @@ DATABASES = {
|
||||||
},
|
},
|
||||||
'legacy': {
|
'legacy': {
|
||||||
'ENGINE': 'django.db.backends.mysql',
|
'ENGINE': 'django.db.backends.mysql',
|
||||||
'HOST': '172.17.0.1',
|
# 'HOST': '172.17.0.1',
|
||||||
# 'HOST': '172.23.0.1',
|
# 'HOST': '172.23.0.1',
|
||||||
# 'HOST': 'mysql_db',
|
'HOST': 'mysql_db',
|
||||||
'PORT': 3306,
|
'PORT': 3306,
|
||||||
'NAME': 'dev',
|
'NAME': 'dev',
|
||||||
'USER': 'dev',
|
'USER': 'dev',
|
||||||
|
|
@ -488,3 +488,5 @@ MEDIA_LOCATION = 'media'
|
||||||
|
|
||||||
PHONENUMBER_DB_FORMAT = 'NATIONAL'
|
PHONENUMBER_DB_FORMAT = 'NATIONAL'
|
||||||
PHONENUMBER_DEFAULT_REGION = "FR"
|
PHONENUMBER_DEFAULT_REGION = "FR"
|
||||||
|
|
||||||
|
FALLBACK_LOCALE = 'en-GB'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user