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.postgres.fields import JSONField
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
import re
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from utils.models import ProjectBaseMixin, URLImageMixin
|
||||
|
|
@ -85,26 +87,64 @@ class Collection(ProjectBaseMixin, CollectionDateMixin,
|
|||
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):
|
||||
"""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):
|
||||
"""Guide model."""
|
||||
parent = models.ForeignKey(
|
||||
'self', verbose_name=_('parent'), on_delete=models.CASCADE,
|
||||
null=True, blank=True, default=None
|
||||
BUILT = 0
|
||||
WAITING = 1
|
||||
REMOVING = 2
|
||||
BUILDING = 3
|
||||
|
||||
STATE_CHOICES = (
|
||||
(BUILT, 'built'),
|
||||
(WAITING, 'waiting'),
|
||||
(REMOVING, 'removing'),
|
||||
(BUILDING, 'building'),
|
||||
|
||||
)
|
||||
advertorials = JSONField(
|
||||
_('advertorials'), null=True, blank=True,
|
||||
default=None, help_text='{"key":"value"}')
|
||||
collection = models.ForeignKey(Collection, on_delete=models.CASCADE,
|
||||
null=True, blank=True, default=None,
|
||||
verbose_name=_('collection'))
|
||||
|
||||
start = models.DateTimeField(null=True,
|
||||
verbose_name=_('start'))
|
||||
vintage = models.IntegerField(validators=[MinValueValidator(1900),
|
||||
MaxValueValidator(2100)],
|
||||
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()
|
||||
|
||||
|
|
@ -116,3 +156,71 @@ class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin):
|
|||
def __str__(self):
|
||||
"""String method."""
|
||||
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
|
||||
'purchased_plaques', # №6 - перенос купленных тарелок
|
||||
'fill_city_gallery', # №3 - перенос галереи городов
|
||||
'guides',
|
||||
'guide_filters',
|
||||
]
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
|
|
|||
|
|
@ -5,11 +5,19 @@
|
|||
# * 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
|
||||
# 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 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)
|
||||
|
||||
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
|
||||
kombu==4.6.6
|
||||
celery==4.3.0
|
||||
|
||||
# country information
|
||||
pycountry==19.8.18
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user