gault-millau/apps/collection/transfer_data.py
2019-12-20 09:26:45 +03:00

396 lines
16 KiB
Python

import operator
from pprint import pprint
from django.db.models import Subquery
from tqdm import tqdm
from collection.models import GuideElementSection, GuideElementSectionCategory, \
GuideWineColorSection, GuideElementType, GuideElement, \
Guide, Advertorial
from establishment.models import Establishment
from gallery.models import Image
from location.models import WineRegion, City
from product.models import Product
from review.models import Review
from transfer.models import Guides, GuideFilters, GuideSections, GuideElements, \
GuideAds, LabelPhotos
from transfer.serializers.guide import GuideSerializer, GuideFilterSerializer
def transfer_guide():
"""Transfer Guide model."""
errors = []
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:
for d in serialized_data.errors: errors.append(d) if d else None
pprint(f"ERRORS: {errors}")
print(f'COUNT OF SERIALIZED OBJECTS: {queryset.values().count()}')
def transfer_guide_filter():
"""Transfer GuideFilter model."""
errors = []
queryset = GuideFilters.objects.exclude(guide__title__icontains='test') \
.exclude(guide__isnull=True)
serialized_data = GuideFilterSerializer(
data=list(queryset.values()),
many=True)
if serialized_data.is_valid():
serialized_data.save()
else:
for d in serialized_data.errors: errors.append(d) if d else None
pprint(f'ERRORS: {errors}')
print(f"COUNT: {len(errors)}")
print(f'COUNT OF SERIALIZED OBJECTS: {queryset.values().count()}')
def transfer_guide_element_section():
"""Transfer GuideSections model."""
created_count = 0
category, _ = GuideElementSectionCategory.objects.get_or_create(
name='shop_category')
queryset_values = GuideSections.objects.values_list('id', 'value_name')
for old_id, section_name in tqdm(queryset_values):
obj, created = GuideElementSection.objects.get_or_create(
name=section_name,
category=category,
old_id=old_id,
)
if created: created_count += 1
print(f'OBJECTS CREATED: {created_count}')
def transfer_guide_wine_color_section():
"""Transfer GuideElements model (only wine color sections)."""
created_count = 0
queryset_values = GuideElements.objects.raw(
"""
select distinct(color),
1 as id
from guide_elements where color is not null;
"""
)
for section_name in tqdm([i.color for i in queryset_values]):
obj, created = GuideWineColorSection.objects.get_or_create(
name=section_name
)
if created: created_count += 1
print(f'OBJECTS CREATED: {created_count}')
def transfer_guide_element_type():
"""Transfer GuideElements model (only element types)."""
created_count = 0
queryset_values = GuideElements.objects.raw(
"""
select distinct(type),
1 as id
from guide_elements;
"""
)
for element_type in tqdm([i.type for i in queryset_values]):
obj, created = GuideElementType.objects.get_or_create(
name=element_type
)
if created: created_count += 1
print(f'OBJECTS CREATED: {created_count}')
def transfer_guide_elements_bulk():
"""Transfer Guide elements via bulk_create."""
def get_guide_element_type(guide_element_type: str):
if guide_element_type:
qs = GuideElementType.objects.filter(name__iexact=guide_element_type)
if qs.exists():
return qs.first()
def get_establishment(old_id: int):
if old_id:
qs = Establishment.objects.filter(old_id=old_id)
if qs.exists():
return qs.first()
def get_review(old_id: int):
if old_id:
qs = Review.objects.filter(old_id=old_id)
if qs.exists():
return qs.first()
def get_wine_region(old_id: int):
if old_id:
qs = WineRegion.objects.filter(old_id=old_id)
if qs.exists():
return qs.first()
def get_wine(old_id: int):
if old_id:
qs = Product.objects.filter(old_id=old_id)
if qs.exists():
return qs.first()
def get_wine_color_section(color_section: str):
if color_section:
qs = GuideWineColorSection.objects.filter(name__iexact=color_section)
if qs.exists():
return qs.first()
def get_city(old_id: int):
if old_id:
qs = City.objects.filter(old_id=old_id)
if qs.exists():
return qs.first()
def get_guide_element_section(old_id: int):
if old_id:
qs = GuideElementSection.objects.filter(old_id=old_id)
if qs.exists():
return qs.first()
def get_guide(old_id):
if old_id:
qs = Guide.objects.filter(old_id=old_id)
if qs.exists():
return qs.first()
def get_parent(old_id):
if old_id:
qs = GuideElement.objects.filter(old_id=old_id)
if qs.exists():
return qs.first()
objects_to_update = []
base_queryset = GuideElements.objects.all()
for old_id, type, establishment_id, review_id, wine_region_id, \
wine_id, color, order_number, city_id, section_id, guide_id \
in tqdm(base_queryset.filter(parent_id__isnull=True)
.values_list('id', 'type', 'establishment_id',
'review_id', 'wine_region_id', 'wine_id',
'color', 'order_number', 'city_id',
'section_id', 'guide_id'),
desc='Check parent guide elements'):
if not GuideElement.objects.filter(old_id=old_id).exists():
guide = GuideElement(
old_id=old_id,
guide_element_type=get_guide_element_type(type),
establishment=get_establishment(establishment_id),
review=get_review(review_id),
wine_region=get_wine_region(wine_region_id),
product=get_wine(wine_id),
wine_color_section=get_wine_color_section(color),
priority=order_number,
city=get_city(city_id),
section=get_guide_element_section(section_id),
parent=None,
lft=1,
rght=1,
tree_id=1,
level=1,
)
# check old guide
if not guide_id:
objects_to_update.append(guide)
else:
old_guide = Guides.objects.exclude(title__icontains='test') \
.filter(id=guide_id)
if old_guide.exists():
guide.guide = get_guide(guide_id)
objects_to_update.append(guide)
# create parents
GuideElement.objects.bulk_create(objects_to_update)
print(f'COUNT OF CREATED OBJECTS: {len(objects_to_update)}')
# attach child guide elements
created_child = 0
queryset_values = base_queryset.exclude(parent_id__isnull=True) \
.values_list('id', 'type', 'establishment_id',
'review_id', 'wine_region_id', 'wine_id',
'color', 'order_number', 'city_id',
'section_id', 'guide_id', 'rgt', 'lft', 'parent_id')
for old_id, type, establishment_id, review_id, wine_region_id, \
wine_id, color, order_number, city_id, section_id, guide_id, \
lft, rgt, parent_id \
in tqdm(sorted(queryset_values, key=lambda value: operator.itemgetter(-2, -1)(value)),
desc='Check child guide elements'):
if not GuideElement.objects.filter(old_id=old_id).exists():
# check old guide
if guide_id:
old_guide = Guides.objects.exclude(title__icontains='test') \
.filter(id=guide_id)
if old_guide.exists():
guide_element, created = GuideElement.objects.get_or_create(
old_id=old_id,
guide_element_type=get_guide_element_type(type),
establishment=get_establishment(establishment_id),
review=get_review(review_id),
wine_region=get_wine_region(wine_region_id),
product=get_wine(wine_id),
wine_color_section=get_wine_color_section(color),
priority=order_number,
city=get_city(city_id),
section=get_guide_element_section(section_id),
parent=get_parent(parent_id),
lft=1,
rght=1,
tree_id=1,
level=1,
guide=get_guide(guide_id),
)
if created: created_child += 1
print(f'CREATED {created_child} OBJECTS')
# rebuild trees
GuideElement._tree_manager.rebuild()
# record the total count of descendants objects
objects_to_update = []
for guide in tqdm(Guide.objects.all(),
desc='update count_of_initial_objects field values'):
root_node = GuideElement.objects.get_root_node(guide)
if root_node:
descendants = root_node.get_descendants()
if descendants:
count_related_objects = descendants.filter(
guide_element_type__name__in=['EstablishmentNode', 'WineNode']).count()
guide.count_related_objects = count_related_objects
objects_to_update.append(guide)
# update count_of_initial_objects field values
Guide.objects.bulk_update(objects_to_update, ['count_related_objects', ])
print(f'COUNT OF UPDATED OBJECTS: {len(objects_to_update)}')
def transfer_guide_element_advertorials():
"""Transfer Guide Advertorials model."""
def get_guide_element(old_id: int):
if old_id:
qs = GuideElement.objects.filter(old_id=old_id)
legacy_qs = GuideElements.objects.exclude(guide__isnull=True) \
.exclude(guide__title__icontains='test') \
.filter(id=old_id)
if qs.exists() and legacy_qs.exists():
return qs.first()
elif legacy_qs.exists() and not qs.exists():
raise ValueError(f'Guide element was not transfer correctly - {old_id}.')
objects_to_update = []
advertorials = GuideAds.objects.exclude(nb_pages__isnull=True) \
.exclude(nb_right_pages__isnull=True) \
.exclude(guide_ad_node_id__isnull=True) \
.values_list('id', 'nb_pages', 'nb_right_pages',
'guide_ad_node_id')
for old_id, nb_pages, nb_right_pages, guide_ad_node_id in tqdm(advertorials):
# check guide element
guide_element = get_guide_element(guide_ad_node_id)
if not Advertorial.objects.filter(old_id=old_id).exists() and guide_element:
objects_to_update.append(
Advertorial(
old_id=old_id,
number_of_pages=nb_pages,
right_pages=nb_right_pages,
guide_element=guide_element,
)
)
# create related child
Advertorial.objects.bulk_create(objects_to_update)
pprint(f'CREATED ADVERTORIALS W/ OLD_ID: {[i.old_id for i in objects_to_update]}')
print(f'COUNT OF CREATED OBJECTS: {len(objects_to_update)}')
def transfer_guide_element_label_photo():
"""Transfer galleries for Guide Advertorial model."""
def get_guide_element(guide_ad):
legacy_guide_element_id = guide_ad.guide_ad_node.id
legacy_guide_element_qs = GuideElements.objects.filter(id=legacy_guide_element_id)
guide_element_qs = GuideElement.objects.filter(old_id=legacy_guide_element_id)
if guide_element_qs.exists() and legacy_guide_element_qs.exists():
return guide_element_qs.first()
else:
raise ValueError(f'Guide element was not transfer correctly - '
f'{legacy_guide_element_id}.')
to_update = []
not_updated = 0
guide_element_label_photos = LabelPhotos.objects.exclude(guide_ad__isnull=True) \
.filter(guide_ad__type='GuideAdLabel') \
.distinct() \
.values_list('guide_ad', 'attachment_suffix_url')
for guide_ad_id, attachment_suffix_url in tqdm(guide_element_label_photos):
legacy_guide_element_ids = Subquery(
GuideElements.objects.exclude(guide__isnull=True)
.exclude(guide__title__icontains='test')
.values_list('id', flat=True)
)
legacy_guide_ad_qs = GuideAds.objects.filter(id=guide_ad_id,
guide_ad_node_id__in=legacy_guide_element_ids)
if legacy_guide_ad_qs.exists():
guide_element = get_guide_element(legacy_guide_ad_qs.first())
if guide_element:
image, _ = Image.objects.get_or_create(image=attachment_suffix_url,
defaults={
'image': attachment_suffix_url,
'orientation': Image.HORIZONTAL,
'title': f'{guide_element.__str__()} '
f'{guide_element.id} - '
f'{attachment_suffix_url}'})
if not guide_element.label_photo:
guide_element.label_photo = image
to_update.append(guide_element)
else:
not_updated += 1
GuideElement.objects.bulk_update(to_update, ['label_photo', ])
print(f'Added label photo to {len(to_update)} objects\n'
f'Objects {not_updated} not updated')
data_types = {
'guides': [
transfer_guide,
],
'guide_filters': [
transfer_guide_filter,
],
'guide_element_sections': [
transfer_guide_element_section,
],
'guide_wine_color_sections': [
transfer_guide_wine_color_section,
],
'guide_element_types': [
transfer_guide_element_type,
],
'guide_elements_bulk': [
transfer_guide_elements_bulk,
],
'guide_element_advertorials': [
transfer_guide_element_advertorials,
],
'guide_element_label_photo': [
transfer_guide_element_label_photo,
],
'guide_complete': [
transfer_guide, # transfer guides from Guides
transfer_guide_filter, # transfer guide filters from GuideFilters
transfer_guide_element_section, # partial transfer element section from GuideSections
transfer_guide_wine_color_section, # partial transfer wine color section from GuideSections
transfer_guide_element_type, # partial transfer section types from GuideElements
transfer_guide_elements_bulk, # transfer result of GuideFilters from GuideElements
transfer_guide_element_advertorials, # transfer advertorials that linked to GuideElements
transfer_guide_element_label_photo, # transfer guide element label photos
]
}