in progress
This commit is contained in:
parent
ca7d7f0fa8
commit
eaeebae72a
120
apps/collection/management/commands/check_guide_dependencies.py
Normal file
120
apps/collection/management/commands/check_guide_dependencies.py
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
import re
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
from establishment.models import Establishment
|
||||||
|
from location.models import City
|
||||||
|
from location.models import WineRegion
|
||||||
|
from product.models import Product
|
||||||
|
from review.models import Review
|
||||||
|
from tag.models import Tag
|
||||||
|
from transfer.models import GuideElements
|
||||||
|
|
||||||
|
|
||||||
|
def decorator(f):
|
||||||
|
def decorate(self):
|
||||||
|
print(f'{"-"*20}start {f.__name__}{"-"*20}')
|
||||||
|
f(self)
|
||||||
|
print(f'{"-"*20}end {f.__name__}{"-"*20}\n')
|
||||||
|
return decorate
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = """Check guide dependencies."""
|
||||||
|
|
||||||
|
@decorator
|
||||||
|
def count_of_guide_relative_dependencies(self):
|
||||||
|
for field in GuideElements._meta.fields:
|
||||||
|
if field.name not in ['id', 'lft', 'rgt', 'depth',
|
||||||
|
'children_count', 'parent', 'order_number']:
|
||||||
|
filters = {f'{field.name}__isnull': False, }
|
||||||
|
qs = GuideElements.objects.filter(**filters).values_list(field.name, flat=True)
|
||||||
|
print(f"COUNT OF {field.name}'s: {len(set(qs))}")
|
||||||
|
|
||||||
|
@decorator
|
||||||
|
def check_regions(self):
|
||||||
|
wine_region_old_ids = set(GuideElements.objects.filter(wine_region_id__isnull=False)
|
||||||
|
.values_list('wine_region_id', flat=True))
|
||||||
|
not_existed_wine_regions = []
|
||||||
|
for old_id in tqdm(wine_region_old_ids):
|
||||||
|
if not WineRegion.objects.filter(old_id=old_id).exists():
|
||||||
|
not_existed_wine_regions.append(old_id)
|
||||||
|
print(f'NOT EXISTED WINE REGIONS: {len(not_existed_wine_regions)}')
|
||||||
|
pprint(f'{not_existed_wine_regions}')
|
||||||
|
|
||||||
|
@decorator
|
||||||
|
def check_establishments(self):
|
||||||
|
establishment_old_ids = set(GuideElements.objects.filter(establishment_id__isnull=False)
|
||||||
|
.values_list('establishment_id', flat=True))
|
||||||
|
not_existed_establishments = []
|
||||||
|
for old_id in tqdm(establishment_old_ids):
|
||||||
|
if not Establishment.objects.filter(old_id=old_id).exists():
|
||||||
|
not_existed_establishments.append(old_id)
|
||||||
|
print(f'NOT EXISTED ESTABLISHMENTS: {len(not_existed_establishments)}')
|
||||||
|
pprint(f'{not_existed_establishments}')
|
||||||
|
|
||||||
|
@decorator
|
||||||
|
def check_reviews(self):
|
||||||
|
review_old_ids = set(GuideElements.objects.filter(review_id__isnull=False)
|
||||||
|
.values_list('review_id', flat=True))
|
||||||
|
not_existed_reviews = []
|
||||||
|
for old_id in tqdm(review_old_ids):
|
||||||
|
if not Review.objects.filter(old_id=old_id).exists():
|
||||||
|
not_existed_reviews.append(old_id)
|
||||||
|
print(f'NOT EXISTED REVIEWS: {len(not_existed_reviews)}')
|
||||||
|
pprint(f'{not_existed_reviews}')
|
||||||
|
|
||||||
|
@decorator
|
||||||
|
def check_wines(self):
|
||||||
|
wine_old_ids = set(GuideElements.objects.filter(wine_id__isnull=False)
|
||||||
|
.values_list('wine_id', flat=True))
|
||||||
|
not_existed_wines = []
|
||||||
|
for old_id in tqdm(wine_old_ids):
|
||||||
|
if not Product.objects.filter(old_id=old_id).exists():
|
||||||
|
not_existed_wines.append(old_id)
|
||||||
|
print(f'NOT EXISTED WINES: {len(not_existed_wines)}')
|
||||||
|
pprint(f'{not_existed_wines}')
|
||||||
|
|
||||||
|
@decorator
|
||||||
|
def check_wine_color(self):
|
||||||
|
raw_wine_color_nodes = set(GuideElements.objects.exclude(color__iexact='')
|
||||||
|
.filter(color__isnull=False)
|
||||||
|
.values_list('color', flat=True))
|
||||||
|
raw_wine_colors = [i[:-11] for i in raw_wine_color_nodes]
|
||||||
|
raw_wine_color_index_names = []
|
||||||
|
re_exp = '[A-Z][^A-Z]*'
|
||||||
|
for raw_wine_color in tqdm(raw_wine_colors):
|
||||||
|
result = re.findall(re_exp, rf'{raw_wine_color}')
|
||||||
|
if result and len(result) >= 2:
|
||||||
|
wine_color = '-'.join(result)
|
||||||
|
else:
|
||||||
|
wine_color = result[0]
|
||||||
|
raw_wine_color_index_names.append(wine_color.lower())
|
||||||
|
not_existed_wine_colors = []
|
||||||
|
for index_name in raw_wine_color_index_names:
|
||||||
|
if not Tag.objects.filter(value=index_name).exists():
|
||||||
|
not_existed_wine_colors.append(index_name)
|
||||||
|
print(f'NOT EXISTED WINE COLOR: {len(not_existed_wine_colors)}')
|
||||||
|
pprint(f'{not_existed_wine_colors}')
|
||||||
|
|
||||||
|
@decorator
|
||||||
|
def check_cities(self):
|
||||||
|
city_old_ids = set(GuideElements.objects.filter(city_id__isnull=False)
|
||||||
|
.values_list('city_id', flat=True))
|
||||||
|
not_existed_cities = []
|
||||||
|
for old_id in tqdm(city_old_ids):
|
||||||
|
if not City.objects.filter(old_id=old_id).exists():
|
||||||
|
not_existed_cities.append(old_id)
|
||||||
|
print(f'NOT EXISTED CITIES: {len(not_existed_cities)}')
|
||||||
|
pprint(f'{not_existed_cities}')
|
||||||
|
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
self.count_of_guide_relative_dependencies()
|
||||||
|
self.check_regions()
|
||||||
|
self.check_establishments()
|
||||||
|
self.check_reviews()
|
||||||
|
self.check_wines()
|
||||||
|
self.check_wine_color()
|
||||||
|
self.check_cities()
|
||||||
78
apps/collection/migrations/0018_auto_20191127_1047.py
Normal file
78
apps/collection/migrations/0018_auto_20191127_1047.py
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Generated by Django 2.2.7 on 2019-11-27 10:47
|
||||||
|
|
||||||
|
import django.contrib.postgres.fields.jsonb
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('main', '0039_sitefeature_old_id'),
|
||||||
|
('collection', '0017_collection_old_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='GuideType',
|
||||||
|
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')),
|
||||||
|
('name', models.SlugField(max_length=255, unique=True, verbose_name='code')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'guide type',
|
||||||
|
'verbose_name_plural': 'guide types',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='guide',
|
||||||
|
name='advertorials',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='guide',
|
||||||
|
name='collection',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='guide',
|
||||||
|
name='parent',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='guide',
|
||||||
|
name='old_id',
|
||||||
|
field=models.IntegerField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='guide',
|
||||||
|
name='site',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='main.SiteSettings', verbose_name='site settings'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='guide',
|
||||||
|
name='slug',
|
||||||
|
field=models.SlugField(max_length=255, null=True, unique=True, verbose_name='slug'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='guide',
|
||||||
|
name='state',
|
||||||
|
field=models.PositiveSmallIntegerField(choices=[(0, 'built'), (1, 'waiting'), (2, 'removing'), (3, 'building')], default=1, verbose_name='state'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='guide',
|
||||||
|
name='vintage',
|
||||||
|
field=models.IntegerField(null=True, validators=[django.core.validators.MinValueValidator(1900), django.core.validators.MaxValueValidator(2100)], verbose_name='guide vintage year'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='guide',
|
||||||
|
name='guide_type',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='collection.GuideType', verbose_name='type'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='guide',
|
||||||
|
name='start',
|
||||||
|
field=models.DateTimeField(null=True, verbose_name='start'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
from django.contrib.contenttypes.fields import ContentType
|
from django.contrib.contenttypes.fields import ContentType
|
||||||
from django.contrib.postgres.fields import JSONField
|
from django.contrib.postgres.fields import JSONField
|
||||||
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
import re
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from utils.models import ProjectBaseMixin, URLImageMixin
|
from utils.models import ProjectBaseMixin, URLImageMixin
|
||||||
|
|
@ -85,26 +87,64 @@ class Collection(ProjectBaseMixin, CollectionDateMixin,
|
||||||
verbose_name_plural = _('collections')
|
verbose_name_plural = _('collections')
|
||||||
|
|
||||||
|
|
||||||
|
class GuideTypeQuerySet(models.QuerySet):
|
||||||
|
"""QuerySet for model GuideType."""
|
||||||
|
|
||||||
|
|
||||||
|
class GuideType(ProjectBaseMixin):
|
||||||
|
"""GuideType model."""
|
||||||
|
|
||||||
|
name = models.SlugField(max_length=255, unique=True,
|
||||||
|
verbose_name=_('code'))
|
||||||
|
|
||||||
|
objects = GuideTypeQuerySet.as_manager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
verbose_name = _('guide type')
|
||||||
|
verbose_name_plural = _('guide types')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""Overridden str dunder method."""
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class GuideQuerySet(models.QuerySet):
|
class GuideQuerySet(models.QuerySet):
|
||||||
"""QuerySet for Guide."""
|
"""QuerySet for Guide."""
|
||||||
|
|
||||||
def by_collection_id(self, collection_id):
|
|
||||||
"""Filter by collection id"""
|
|
||||||
return self.filter(collection=collection_id)
|
|
||||||
|
|
||||||
|
|
||||||
class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin):
|
class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin):
|
||||||
"""Guide model."""
|
"""Guide model."""
|
||||||
parent = models.ForeignKey(
|
BUILT = 0
|
||||||
'self', verbose_name=_('parent'), on_delete=models.CASCADE,
|
WAITING = 1
|
||||||
null=True, blank=True, default=None
|
REMOVING = 2
|
||||||
|
BUILDING = 3
|
||||||
|
|
||||||
|
STATE_CHOICES = (
|
||||||
|
(BUILT, 'built'),
|
||||||
|
(WAITING, 'waiting'),
|
||||||
|
(REMOVING, 'removing'),
|
||||||
|
(BUILDING, 'building'),
|
||||||
|
|
||||||
)
|
)
|
||||||
advertorials = JSONField(
|
|
||||||
_('advertorials'), null=True, blank=True,
|
start = models.DateTimeField(null=True,
|
||||||
default=None, help_text='{"key":"value"}')
|
verbose_name=_('start'))
|
||||||
collection = models.ForeignKey(Collection, on_delete=models.CASCADE,
|
vintage = models.IntegerField(validators=[MinValueValidator(1900),
|
||||||
null=True, blank=True, default=None,
|
MaxValueValidator(2100)],
|
||||||
verbose_name=_('collection'))
|
null=True,
|
||||||
|
verbose_name=_('guide vintage year'))
|
||||||
|
slug = models.SlugField(max_length=255, unique=True, null=True,
|
||||||
|
verbose_name=_('slug'))
|
||||||
|
guide_type = models.ForeignKey('GuideType', on_delete=models.PROTECT,
|
||||||
|
null=True,
|
||||||
|
verbose_name=_('type'))
|
||||||
|
site = models.ForeignKey('main.SiteSettings', on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
verbose_name=_('site settings'))
|
||||||
|
state = models.PositiveSmallIntegerField(default=WAITING, choices=STATE_CHOICES,
|
||||||
|
verbose_name=_('state'))
|
||||||
|
old_id = models.IntegerField(blank=True, null=True)
|
||||||
|
|
||||||
objects = GuideQuerySet.as_manager()
|
objects = GuideQuerySet.as_manager()
|
||||||
|
|
||||||
|
|
@ -116,3 +156,71 @@ class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""String method."""
|
"""String method."""
|
||||||
return f'{self.name}'
|
return f'{self.name}'
|
||||||
|
|
||||||
|
|
||||||
|
class AdvertorialQuerySet(models.QuerySet):
|
||||||
|
"""QuerySet for model Advertorial."""
|
||||||
|
|
||||||
|
|
||||||
|
class Advertorial(ProjectBaseMixin):
|
||||||
|
"""Guide advertorial model."""
|
||||||
|
number_of_pages = models.PositiveIntegerField(
|
||||||
|
verbose_name=_('number of pages'),
|
||||||
|
help_text=_('the total number of reserved pages'))
|
||||||
|
right_pages = models.PositiveIntegerField(
|
||||||
|
verbose_name=_('number of right pages'),
|
||||||
|
help_text=_('the number of right pages (which are part of total number).'))
|
||||||
|
old_id = models.IntegerField(blank=True, null=True)
|
||||||
|
|
||||||
|
objects = AdvertorialQuerySet.as_manager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
verbose_name = _('advertorial')
|
||||||
|
verbose_name_plural = _('advertorials')
|
||||||
|
|
||||||
|
|
||||||
|
class GuideFilterQuerySet(models.QuerySet):
|
||||||
|
"""QuerySet for model GuideFilter."""
|
||||||
|
|
||||||
|
|
||||||
|
class GuideFilter(ProjectBaseMixin):
|
||||||
|
"""Guide filter model."""
|
||||||
|
establishment_type_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='establishment types')
|
||||||
|
country_code_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='countries')
|
||||||
|
region_code_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='regions')
|
||||||
|
sub_region_code_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='sub regions')
|
||||||
|
wine_region_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='wine regions')
|
||||||
|
wine_classification_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='wine classifications')
|
||||||
|
wine_color_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='wine colors')
|
||||||
|
wine_type_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='wine types')
|
||||||
|
with_mark = models.BooleanField(default=True,
|
||||||
|
verbose_name=_('with mark'),
|
||||||
|
help_text=_('exclude empty marks?'))
|
||||||
|
locale_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='locales')
|
||||||
|
max_mark = models.PositiveSmallIntegerField(verbose_name=_('max mark'),
|
||||||
|
help_text=_('mark under'))
|
||||||
|
min_mark = models.PositiveSmallIntegerField(verbose_name=_('min mark'),
|
||||||
|
help_text=_('mark over'))
|
||||||
|
review_vintage_json = JSONField(verbose_name='review vintage years')
|
||||||
|
review_state_json = JSONField(blank=True, null=True,
|
||||||
|
verbose_name='review states')
|
||||||
|
guide = models.OneToOneField(Guide, on_delete=models.CASCADE,
|
||||||
|
verbose_name=_('guide'))
|
||||||
|
old_id = models.IntegerField(blank=True, null=True)
|
||||||
|
|
||||||
|
objects = GuideFilterQuerySet.as_manager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
verbose_name = _('guide filter')
|
||||||
|
verbose_name_plural = _('guide filters')
|
||||||
|
|
|
||||||
37
apps/collection/transfer_data.py
Normal file
37
apps/collection/transfer_data.py
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
from pprint import pprint
|
||||||
|
from transfer.models import Guides, GuideFilters
|
||||||
|
from transfer.serializers.guide import GuideSerializer, GuideFilterSerializer
|
||||||
|
|
||||||
|
|
||||||
|
def transfer_guide():
|
||||||
|
"""Transfer Guide model."""
|
||||||
|
queryset = Guides.objects.exclude(title__icontains='test')
|
||||||
|
serialized_data = GuideSerializer(
|
||||||
|
data=list(queryset.values()),
|
||||||
|
many=True)
|
||||||
|
if serialized_data.is_valid():
|
||||||
|
serialized_data.save()
|
||||||
|
else:
|
||||||
|
pprint(f"transfer guide errors: {serialized_data.errors}")
|
||||||
|
|
||||||
|
|
||||||
|
def transfer_guide_filter():
|
||||||
|
"""Transfer GuideFilter model."""
|
||||||
|
queryset = GuideFilters.objects.all()
|
||||||
|
serialized_data = GuideFilterSerializer(
|
||||||
|
data=list(queryset.values()),
|
||||||
|
many=True)
|
||||||
|
if serialized_data.is_valid():
|
||||||
|
serialized_data.save()
|
||||||
|
else:
|
||||||
|
pprint(f"transfer guide filter errors: {serialized_data.errors}")
|
||||||
|
|
||||||
|
|
||||||
|
data_types = {
|
||||||
|
'guides': [
|
||||||
|
transfer_guide,
|
||||||
|
],
|
||||||
|
'guide_filters': [
|
||||||
|
transfer_guide_filter,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -41,6 +41,8 @@ class Command(BaseCommand):
|
||||||
'newsletter_subscriber', # подписчики на рассылку - переносить после переноса пользователей №1
|
'newsletter_subscriber', # подписчики на рассылку - переносить после переноса пользователей №1
|
||||||
'purchased_plaques', # №6 - перенос купленных тарелок
|
'purchased_plaques', # №6 - перенос купленных тарелок
|
||||||
'fill_city_gallery', # №3 - перенос галереи городов
|
'fill_city_gallery', # №3 - перенос галереи городов
|
||||||
|
'guides',
|
||||||
|
'guide_filters',
|
||||||
]
|
]
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,19 @@
|
||||||
# * Make sure each ForeignKey has `on_delete` set to the desired behavior.
|
# * Make sure each ForeignKey has `on_delete` set to the desired behavior.
|
||||||
# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
|
# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
|
||||||
# Feel free to rename the models, but don't rename db_table values or field names.
|
# Feel free to rename the models, but don't rename db_table values or field names.
|
||||||
|
import yaml
|
||||||
from django.contrib.gis.db import models
|
from django.contrib.gis.db import models
|
||||||
|
|
||||||
from transfer.mixins import MigrateMixin
|
from transfer.mixins import MigrateMixin
|
||||||
|
|
||||||
|
|
||||||
|
def convert_entry(loader, node):
|
||||||
|
return {e[0]: e[1] for e in loader.construct_pairs(node)}
|
||||||
|
|
||||||
|
|
||||||
|
yaml.add_constructor('!ruby/hash:ActiveSupport::HashWithIndifferentAccess', convert_entry)
|
||||||
|
|
||||||
|
|
||||||
# models.ForeignKey(ForeignModel, models.DO_NOTHING, blank=True, null=True)
|
# models.ForeignKey(ForeignModel, models.DO_NOTHING, blank=True, null=True)
|
||||||
|
|
||||||
class Sites(MigrateMixin):
|
class Sites(MigrateMixin):
|
||||||
|
|
|
||||||
283
apps/transfer/serializers/guide.py
Normal file
283
apps/transfer/serializers/guide.py
Normal file
|
|
@ -0,0 +1,283 @@
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
from pycountry import countries, subdivisions
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from collection.models import Guide, GuideType, GuideFilter
|
||||||
|
from establishment.models import EstablishmentType
|
||||||
|
from location.models import Country, Region
|
||||||
|
from main.models import SiteSettings
|
||||||
|
from transfer.mixins import TransferSerializerMixin
|
||||||
|
|
||||||
|
|
||||||
|
class GuideSerializer(TransferSerializerMixin):
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
title = serializers.CharField()
|
||||||
|
vintage = serializers.IntegerField()
|
||||||
|
slug = serializers.CharField()
|
||||||
|
state = serializers.CharField()
|
||||||
|
site_id = serializers.IntegerField()
|
||||||
|
inserter_field = serializers.CharField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Guide
|
||||||
|
fields = (
|
||||||
|
'id',
|
||||||
|
'title',
|
||||||
|
'vintage',
|
||||||
|
'slug',
|
||||||
|
'state',
|
||||||
|
'site_id',
|
||||||
|
'inserter_field',
|
||||||
|
)
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
"""Overridden validate method."""
|
||||||
|
attrs['old_id'] = attrs.pop('id')
|
||||||
|
attrs['name'] = attrs.pop('title')
|
||||||
|
attrs['vintage'] = int(attrs.pop('vintage'))
|
||||||
|
attrs['state'] = self.get_state(attrs.pop('state'))
|
||||||
|
attrs['site'] = self.get_site(attrs.pop('site_id'))
|
||||||
|
attrs['guide_type'] = self.get_guide_type(attrs.pop('inserter_field'))
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def get_state(self, state: str):
|
||||||
|
if state == 'built':
|
||||||
|
return Guide.BUILT
|
||||||
|
elif state == 'removing':
|
||||||
|
return Guide.REMOVING
|
||||||
|
elif state == 'building':
|
||||||
|
return Guide.BUILDING
|
||||||
|
else:
|
||||||
|
return Guide.WAITING
|
||||||
|
|
||||||
|
def get_site(self, site_id):
|
||||||
|
qs = SiteSettings.objects.filter(old_id=site_id)
|
||||||
|
if qs.exists():
|
||||||
|
return qs.first()
|
||||||
|
|
||||||
|
def get_guide_type(self, inserter_field):
|
||||||
|
guide_type, _ = GuideType.objects.get_or_create(name=inserter_field)
|
||||||
|
return guide_type
|
||||||
|
|
||||||
|
|
||||||
|
class GuideFilterSerializer(TransferSerializerMixin):
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
year = serializers.CharField()
|
||||||
|
establishment_type = serializers.CharField(allow_null=True)
|
||||||
|
countries = serializers.CharField(allow_null=True)
|
||||||
|
regions = serializers.CharField(allow_null=True)
|
||||||
|
subregions = serializers.CharField(allow_null=True)
|
||||||
|
wine_regions = serializers.CharField(allow_null=True)
|
||||||
|
wine_classifications = serializers.CharField(allow_null=True)
|
||||||
|
wine_colors = serializers.CharField(allow_null=True)
|
||||||
|
wine_types = serializers.CharField(allow_null=True)
|
||||||
|
locales = serializers.CharField(allow_null=True)
|
||||||
|
states = serializers.CharField(allow_null=True)
|
||||||
|
|
||||||
|
max_mark = serializers.IntegerField(allow_null=True)
|
||||||
|
min_mark = serializers.IntegerField(allow_null=True)
|
||||||
|
marks_only = serializers.NullBooleanField()
|
||||||
|
guide_id = serializers.IntegerField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = GuideFilter
|
||||||
|
fields = (
|
||||||
|
'id',
|
||||||
|
'year',
|
||||||
|
'establishment_type',
|
||||||
|
'countries',
|
||||||
|
'regions',
|
||||||
|
'subregions',
|
||||||
|
'wine_regions',
|
||||||
|
'wine_classifications',
|
||||||
|
'wine_colors',
|
||||||
|
'wine_types',
|
||||||
|
'max_mark',
|
||||||
|
'min_mark',
|
||||||
|
'marks_only',
|
||||||
|
'locales',
|
||||||
|
'states',
|
||||||
|
'guide_id',
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_ruby_helper(raw_value: str):
|
||||||
|
"""Parse RubyActiveSupport records"""
|
||||||
|
def convert_entry(loader, node):
|
||||||
|
return {e[0]: e[1] for e in loader.construct_pairs(node)}
|
||||||
|
|
||||||
|
loader = yaml.Loader
|
||||||
|
loader.add_constructor('!ruby/hash:ActiveSupport::HashWithIndifferentAccess', convert_entry)
|
||||||
|
return yaml.load(raw_value, Loader=loader) if raw_value else None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_country_alpha_2(country_code_alpha3: str):
|
||||||
|
country = countries.get(alpha_3=country_code_alpha3.upper())
|
||||||
|
return {'code_alpha_2': country.alpha2.lower() if country else None,
|
||||||
|
'name': country.name if country else None,}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_dictionary(dictionary: dict):
|
||||||
|
"""
|
||||||
|
Exclude root values from dictionary.
|
||||||
|
Convert {key_2: [value_1, value_2]} into
|
||||||
|
[value_1, value_2]
|
||||||
|
"""
|
||||||
|
return list(chain.from_iterable(dictionary.values()))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_nested_dictionary(dictionary: dict):
|
||||||
|
"""
|
||||||
|
Exclude root values from dictionary.
|
||||||
|
Convert {key_1: {key_2: [value_1, value_2]}} into
|
||||||
|
[value_1, value_2]
|
||||||
|
"""
|
||||||
|
l = []
|
||||||
|
for i in dictionary:
|
||||||
|
l.append(list(chain.from_iterable(list(dictionary[i].values()))))
|
||||||
|
return list(chain.from_iterable(l))
|
||||||
|
|
||||||
|
def get_country(self, code_alpha_3: str) -> Country:
|
||||||
|
country = self.get_country_alpha_2(code_alpha_3)
|
||||||
|
country_name = country['name']
|
||||||
|
country_code = country['code_alpha_2']
|
||||||
|
if country_name and country_code:
|
||||||
|
country, _ = Country.objects.get_or_create(
|
||||||
|
code__icontains=country_code,
|
||||||
|
name__contains={'en-GB': country_name},
|
||||||
|
defaults={
|
||||||
|
'code': country_code,
|
||||||
|
'name': {'en-GB': country_name}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return country
|
||||||
|
|
||||||
|
def get_region(self, region_code_alpha_3: str,
|
||||||
|
country_code_alpha_3: str,
|
||||||
|
sub_region_code_alpha_3: str = None):
|
||||||
|
country = self.get_country(country_code_alpha_3)
|
||||||
|
country_code_alpha_2 = country.code.upper()
|
||||||
|
region_qs = Region.objects.filter(code__iexact=region_code_alpha_3,
|
||||||
|
country__code__iexact=country_code_alpha_2)
|
||||||
|
|
||||||
|
# If region isn't existed, check sub region for parent_code (region code)
|
||||||
|
if not region_qs.exists() and sub_region_code_alpha_3:
|
||||||
|
# sub region
|
||||||
|
subdivision = subdivisions.get(
|
||||||
|
code=f"{country_code_alpha_2}-{sub_region_code_alpha_3}")
|
||||||
|
if subdivision:
|
||||||
|
subdivision_region = subdivisions.get(parent_code=subdivision.parent_code)
|
||||||
|
obj = Region.objects.create(
|
||||||
|
name=subdivision_region.name,
|
||||||
|
code=subdivision_region.code,
|
||||||
|
country=country)
|
||||||
|
return obj
|
||||||
|
else:
|
||||||
|
return region_qs.first()
|
||||||
|
|
||||||
|
def validate_year(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_establishment_type(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_countries(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_regions(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_sub_regions(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_wine_regions(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_wine_classifications(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_wine_colors(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_wine_types(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_locales(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate_states(self, value):
|
||||||
|
return self.parse_ruby_helper(value)
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
sub_regions = attrs.pop('subregions')
|
||||||
|
regions = attrs.pop('regions')
|
||||||
|
|
||||||
|
attrs['old_id'] = attrs.pop('id')
|
||||||
|
attrs['review_vintage_json'] = self.get_review_vintage(self.attrs.pop('year'))
|
||||||
|
attrs['establishment_type_json'] = self.get_establishment_type_ids(
|
||||||
|
self.attrs.pop('establishment_type'))
|
||||||
|
attrs['country_code_json'] = self.get_country_ids(attrs.pop('country_json'))
|
||||||
|
attrs['region_json'] = self.get_region_ids(regions, sub_regions)
|
||||||
|
attrs['sub_region_json'] = self.get_sub_region_ids(regions, sub_regions)
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def get_review_vintage(self, year):
|
||||||
|
return {'vintage': [int(i) for i in set(year) if i.isdigit()]}
|
||||||
|
|
||||||
|
def get_establishment_type_ids(self, establishment_types):
|
||||||
|
establishment_type_ids = []
|
||||||
|
for establishment_type in establishment_types:
|
||||||
|
establishment_type_qs = EstablishmentType.objects.filter(index_name__iexact=establishment_type)
|
||||||
|
if not establishment_type_qs.exists():
|
||||||
|
obj = EstablishmentType.objects.create(
|
||||||
|
name={'en-GB': establishment_type.capitalize},
|
||||||
|
index_name=establishment_type.lower())
|
||||||
|
establishment_type_ids.append(obj.id)
|
||||||
|
return {'id': establishment_type_ids}
|
||||||
|
|
||||||
|
def get_country_ids(self, country_codes_alpha_3):
|
||||||
|
country_ids = []
|
||||||
|
for code_alpha_3 in country_codes_alpha_3:
|
||||||
|
country_ids.append(self.get_country(code_alpha_3).id)
|
||||||
|
return {'id': country_ids}
|
||||||
|
|
||||||
|
def get_region_ids(self, regions, sub_regions):
|
||||||
|
region_ids = []
|
||||||
|
for country_code_alpha_3 in regions:
|
||||||
|
region_codes = regions[country_code_alpha_3]
|
||||||
|
for region_code_alpha_3 in region_codes:
|
||||||
|
region = self.get_region(
|
||||||
|
region_code_alpha_3=region_code_alpha_3,
|
||||||
|
country_code_alpha_3=country_code_alpha_3,
|
||||||
|
sub_region_code_alpha_3=sub_regions[country_code_alpha_3][region_code_alpha_3])
|
||||||
|
if region:
|
||||||
|
region_ids.append(region.id)
|
||||||
|
return {'id': region_ids}
|
||||||
|
|
||||||
|
def get_sub_region_ids(self, sub_regions):
|
||||||
|
sub_region_ids = []
|
||||||
|
for country_code_alpha_3 in sub_regions:
|
||||||
|
for region_code_alpha_3 in sub_regions[country_code_alpha_3]:
|
||||||
|
region_codes = sub_regions[country_code_alpha_3][region_code_alpha_3]
|
||||||
|
for sub_region_code_alpha_3 in region_codes:
|
||||||
|
region = self.get_region(
|
||||||
|
region_code_alpha_3=region_code_alpha_3,
|
||||||
|
country_code_alpha_3=country_code_alpha_3,
|
||||||
|
sub_region_code_alpha_3=sub_region_code_alpha_3)
|
||||||
|
if region:
|
||||||
|
subdivision = subdivisions.get(parent_code=region.code.upper())
|
||||||
|
if subdivision:
|
||||||
|
sub_region = Region.objects.create(
|
||||||
|
name=subdivision.name,
|
||||||
|
code=subdivisions.code,
|
||||||
|
parent_region=region,
|
||||||
|
country=region.country)
|
||||||
|
sub_region_ids.append(sub_region.id)
|
||||||
|
|
||||||
|
return {'id': sub_region_ids}
|
||||||
|
|
||||||
|
|
||||||
|
# {'FRA': ['H', 'U']} REGIONS
|
||||||
|
# {'FRA': {'N': ['32']}} SUB REGIONS
|
||||||
|
|
@ -57,3 +57,6 @@ redis==3.2.0
|
||||||
django_redis==4.10.0 # used byes indexing cache
|
django_redis==4.10.0 # used byes indexing cache
|
||||||
kombu==4.6.6
|
kombu==4.6.6
|
||||||
celery==4.3.0
|
celery==4.3.0
|
||||||
|
|
||||||
|
# country information
|
||||||
|
pycountry==19.8.18
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user