add export for guides
This commit is contained in:
parent
1189b6ff58
commit
02d0112d8b
|
|
@ -230,3 +230,32 @@ class AdvertorialBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
attrs['guide_element'] = guide_element
|
attrs['guide_element'] = guide_element
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
|
class GuideElementExportSerializer(GuideElementBaseSerializer):
|
||||||
|
"""GuideElement export serializer."""
|
||||||
|
# establishment = EstablishmentGuideElementSerializer(read_only=True,)
|
||||||
|
name = serializers.CharField(source='establishment.name', default=None)
|
||||||
|
public_mark = serializers.CharField(source='establishment.public_mark', default=None)
|
||||||
|
toque_number = serializers.CharField(source='establishment.toque_number', default=None)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = models.GuideElement
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'node_name',
|
||||||
|
# 'establishment',
|
||||||
|
# 'review',
|
||||||
|
# 'wine_region',
|
||||||
|
# 'product_detail',
|
||||||
|
# 'priority',
|
||||||
|
'city_name',
|
||||||
|
# 'section_name',
|
||||||
|
# 'wine_color_section_name',
|
||||||
|
# 'children',
|
||||||
|
# 'label_photo',
|
||||||
|
'name',
|
||||||
|
'public_mark',
|
||||||
|
'toque_number'
|
||||||
|
|
||||||
|
]
|
||||||
|
|
@ -127,3 +127,22 @@ def generate_product_guide_elements(guide_id: int, queryset_values: dict):
|
||||||
f'DETAIL: Guide ID {guide_id} - {e}')
|
f'DETAIL: Guide ID {guide_id} - {e}')
|
||||||
else:
|
else:
|
||||||
guide.update_count_related_objects()
|
guide.update_count_related_objects()
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def export_guide(guide_id, user_id, file_type='csv'):
|
||||||
|
from collection.models import GuideElement, Guide
|
||||||
|
from collection.serializers import GuideElementExportSerializer
|
||||||
|
from account.models import User
|
||||||
|
from utils.export import SendGuideExport
|
||||||
|
|
||||||
|
user = User.objects.get(id=user_id)
|
||||||
|
guide = Guide.objects.get(id=guide_id)
|
||||||
|
root = GuideElement.objects.get_root_node(guide)
|
||||||
|
if root:
|
||||||
|
nodes = root.get_descendants()
|
||||||
|
serializer = GuideElementExportSerializer(nodes, many=True)
|
||||||
|
data = serializer.data
|
||||||
|
SendGuideExport(
|
||||||
|
data=data, guide=guide, user=user, file_type=file_type
|
||||||
|
).send()
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,10 @@ urlpatterns = [
|
||||||
name='guide-advertorial-destroy'),
|
name='guide-advertorial-destroy'),
|
||||||
path('guides/<int:pk>/filters/', views.GuideFilterCreateView.as_view(),
|
path('guides/<int:pk>/filters/', views.GuideFilterCreateView.as_view(),
|
||||||
name='guide-filter-list-create'),
|
name='guide-filter-list-create'),
|
||||||
|
path('guides/<int:pk>/export-csv/', views.GuideElementExportCSVView.as_view(),
|
||||||
|
name='guide-export-csv'),
|
||||||
|
path('guides/<int:pk>/export-xml/', views.GuideElementExportXMLView.as_view(),
|
||||||
|
name='guide-export-xml'),
|
||||||
|
path('guides/<int:pk>/export-doc/', views.GuideElementExportDOCView.as_view(),
|
||||||
|
name='guide-export-doc'),
|
||||||
] + router.urls
|
] + router.urls
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from rest_framework import generics
|
from rest_framework import generics
|
||||||
from rest_framework import mixins, permissions, viewsets
|
from rest_framework import mixins, permissions, viewsets
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.filters import OrderingFilter
|
from rest_framework.filters import OrderingFilter
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from django.shortcuts import get_object_or_404
|
|
||||||
|
|
||||||
from collection import models, serializers
|
from collection import models, serializers
|
||||||
|
from collection import tasks
|
||||||
from utils.views import BindObjectMixin
|
from utils.views import BindObjectMixin
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -161,3 +163,35 @@ class AdvertorialDestroyView(AdvertorialBaseView,
|
||||||
def delete(self, request, *args, **kwargs):
|
def delete(self, request, *args, **kwargs):
|
||||||
"""Overridden delete method."""
|
"""Overridden delete method."""
|
||||||
return self.destroy(request, *args, **kwargs)
|
return self.destroy(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class GuideElementExportCSVView(generics.ListAPIView):
|
||||||
|
"""Guide element export csv view."""
|
||||||
|
pagination_class = None
|
||||||
|
queryset = models.GuideElement.objects.all()
|
||||||
|
serializer_class = serializers.GuideElementBaseSerializer
|
||||||
|
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
"""Overridden get_queryset method."""
|
||||||
|
guide = get_object_or_404(
|
||||||
|
models.Guide.objects.all(), pk=self.kwargs.get('pk'))
|
||||||
|
tasks.export_guide(guide_id=guide.id, user_id=request.user.id)
|
||||||
|
return Response({"success": _('The file will be sent to your email.')},
|
||||||
|
status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
class GuideElementExportXMLView(generics.ListAPIView):
|
||||||
|
"""Guide element export xml view."""
|
||||||
|
pagination_class = None
|
||||||
|
queryset = models.GuideElement.objects.all()
|
||||||
|
serializer_class = serializers.GuideElementBaseSerializer
|
||||||
|
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
||||||
|
|
||||||
|
|
||||||
|
class GuideElementExportDOCView(generics.ListAPIView):
|
||||||
|
"""Guide element export doc view."""
|
||||||
|
pagination_class = None
|
||||||
|
queryset = models.GuideElement.objects.all()
|
||||||
|
serializer_class = serializers.GuideElementBaseSerializer
|
||||||
|
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
||||||
|
|
|
||||||
|
|
@ -646,6 +646,7 @@ class EstablishmentGuideElementSerializer(serializers.ModelSerializer):
|
||||||
fields = [
|
fields = [
|
||||||
'id',
|
'id',
|
||||||
'type',
|
'type',
|
||||||
|
'name',
|
||||||
'subtypes',
|
'subtypes',
|
||||||
'address',
|
'address',
|
||||||
'tz',
|
'tz',
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,4 @@ from utils.export import SendExport
|
||||||
def send_export_to_email(panel_id, user_id, file_type='csv'):
|
def send_export_to_email(panel_id, user_id, file_type='csv'):
|
||||||
panel = Panel.objects.get(id=panel_id)
|
panel = Panel.objects.get(id=panel_id)
|
||||||
user = User.objects.get(id=user_id)
|
user = User.objects.get(id=user_id)
|
||||||
SendExport(user, panel, file_type).send()
|
SendExport(user, panel=panel, file_type=file_type).send()
|
||||||
|
|
|
||||||
|
|
@ -7,46 +7,48 @@ from smtplib import SMTPException
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.mail import EmailMultiAlternatives
|
from django.core.mail import EmailMultiAlternatives
|
||||||
|
import abc
|
||||||
|
|
||||||
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.INFO)
|
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.INFO)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SendExport:
|
class SendExportBase:
|
||||||
|
"""Base class of export and sending data."""
|
||||||
|
|
||||||
def __init__(self, user, panel, file_type='csv'):
|
def __init__(self):
|
||||||
self.type_mapper = {
|
self.success = False
|
||||||
"csv": self.make_csv_file,
|
|
||||||
"xls": self.make_xls_file
|
|
||||||
}
|
|
||||||
self.file_type = file_type
|
|
||||||
self.user = user
|
|
||||||
self.panel = panel
|
|
||||||
self.email_from = settings.EMAIL_HOST_USER
|
self.email_from = settings.EMAIL_HOST_USER
|
||||||
self.email_subject = f'Export panel: {self.get_file_name()}'
|
self.email_subject = f'Export panel: {self.get_file_name()}'
|
||||||
self.email_body = 'Exported panel data'
|
self.email_body = 'Exported panel data'
|
||||||
self.get_file_method = self.type_mapper[file_type]
|
|
||||||
self.file_path = os.path.join(
|
self.file_path = os.path.join(
|
||||||
settings.STATIC_ROOT,
|
settings.STATIC_ROOT,
|
||||||
'email', tempfile.gettempdir(),
|
'email', tempfile.gettempdir(),
|
||||||
self.get_file_name()
|
self.get_file_name()
|
||||||
)
|
)
|
||||||
self.success = False
|
self.type_mapper = {
|
||||||
|
"csv": self.make_csv_file,
|
||||||
def get_file_name(self):
|
"xls": self.make_xls_file
|
||||||
name = '_'.join(self.panel.name.split(' '))
|
}
|
||||||
return f'export_{name.lower()}.{self.file_type}'
|
|
||||||
|
|
||||||
def get_data(self):
|
|
||||||
return self.panel.get_data()
|
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
def get_headers(self):
|
def get_headers(self):
|
||||||
try:
|
pass
|
||||||
header = self.panel.get_headers()
|
|
||||||
self.success = True
|
@abc.abstractmethod
|
||||||
return header
|
def get_emails_to(self):
|
||||||
except Exception as err:
|
return [
|
||||||
logger.info(f'HEADER:{err}')
|
'kuzmenko.da@gmail.com',
|
||||||
|
'sinapsit@yandex.ru'
|
||||||
|
]
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_data(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_file_name(self):
|
||||||
|
return ''
|
||||||
|
|
||||||
def make_csv_file(self):
|
def make_csv_file(self):
|
||||||
file_header = self.get_headers()
|
file_header = self.get_headers()
|
||||||
|
|
@ -77,17 +79,8 @@ class SendExport:
|
||||||
worksheet.write_row(f'A{n+2}', [str(i) for i in row])
|
worksheet.write_row(f'A{n+2}', [str(i) for i in row])
|
||||||
workbook.close()
|
workbook.close()
|
||||||
|
|
||||||
def send(self):
|
def make_xml_file(self):
|
||||||
self.get_file_method()
|
pass
|
||||||
print(f'ok: {self.file_path}')
|
|
||||||
self.send_email()
|
|
||||||
|
|
||||||
def get_file(self):
|
|
||||||
if os.path.exists(self.file_path) and os.path.isfile(self.file_path):
|
|
||||||
with open(self.file_path, 'rb') as export_file:
|
|
||||||
return export_file
|
|
||||||
else:
|
|
||||||
logger.info('COMMUTATOR:image file not found dir: {path}')
|
|
||||||
|
|
||||||
def send_email(self):
|
def send_email(self):
|
||||||
|
|
||||||
|
|
@ -95,11 +88,7 @@ class SendExport:
|
||||||
subject=self.email_subject,
|
subject=self.email_subject,
|
||||||
body=self.email_body,
|
body=self.email_body,
|
||||||
from_email=self.email_from,
|
from_email=self.email_from,
|
||||||
to=[
|
to=self.get_emails_to()
|
||||||
self.user.email,
|
|
||||||
'kuzmenko.da@gmail.com',
|
|
||||||
'sinapsit@yandex.ru'
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create an inline attachment
|
# Create an inline attachment
|
||||||
|
|
@ -112,4 +101,107 @@ class SendExport:
|
||||||
msg.send()
|
msg.send()
|
||||||
logger.debug(f"COMMUTATOR:Email successfully sent")
|
logger.debug(f"COMMUTATOR:Email successfully sent")
|
||||||
except SMTPException as e:
|
except SMTPException as e:
|
||||||
logger.error(f"COMMUTATOR:Email connector: {e}")
|
logger.error(f"COMMUTATOR:Email connector: {e}")
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def send(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SendExport(SendExportBase):
|
||||||
|
|
||||||
|
def __init__(self, panel, user, file_type='csv', **kwargs):
|
||||||
|
super().__init__()
|
||||||
|
self.panel = panel
|
||||||
|
self.user = user
|
||||||
|
self.file_type = file_type
|
||||||
|
self.get_file_method = self.type_mapper[file_type]
|
||||||
|
|
||||||
|
def get_emails_to(self):
|
||||||
|
return [self.user.email] + super().get_emails_to()
|
||||||
|
|
||||||
|
def get_file_name(self):
|
||||||
|
name = '_'.join(self.panel.name.split(' '))
|
||||||
|
return f'export_{name.lower()}.{self.file_type}'
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
return self.panel.get_data()
|
||||||
|
|
||||||
|
def get_headers(self):
|
||||||
|
try:
|
||||||
|
header = self.panel.get_headers()
|
||||||
|
self.success = True
|
||||||
|
return header
|
||||||
|
except Exception as err:
|
||||||
|
logger.info(f'HEADER:{err}')
|
||||||
|
|
||||||
|
def get_file(self):
|
||||||
|
if os.path.exists(self.file_path) and os.path.isfile(self.file_path):
|
||||||
|
with open(self.file_path, 'rb') as export_file:
|
||||||
|
return export_file
|
||||||
|
else:
|
||||||
|
logger.info('COMMUTATOR:image file not found dir: {path}')
|
||||||
|
|
||||||
|
def send(self):
|
||||||
|
self.get_file_method()
|
||||||
|
print(f'ok: {self.file_path}')
|
||||||
|
self.send_email()
|
||||||
|
|
||||||
|
|
||||||
|
class SendGuideExport(SendExportBase):
|
||||||
|
"""Send guid export."""
|
||||||
|
|
||||||
|
def __init__(self, data, guide, user, file_type='csv', **kwargs):
|
||||||
|
|
||||||
|
self.type_mapper = {
|
||||||
|
"csv": self.make_csv_file,
|
||||||
|
"xml": self.make_xml_file,
|
||||||
|
"doc": self.make_doc_file
|
||||||
|
}
|
||||||
|
self.guide = guide
|
||||||
|
self.data = data
|
||||||
|
self.user = user
|
||||||
|
self.file_type = file_type
|
||||||
|
self.get_file_method = self.type_mapper[file_type]
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def get_file_name(self):
|
||||||
|
name = self.guide.slug
|
||||||
|
return f'export_{name}.{self.file_type}'
|
||||||
|
|
||||||
|
def make_doc_file(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_headers(self):
|
||||||
|
headers = list(self.data[0].keys())
|
||||||
|
headers.pop(headers.index('node_name'))
|
||||||
|
self.success = True
|
||||||
|
return headers
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def send(self):
|
||||||
|
self.get_file_method()
|
||||||
|
print(f'ok: {self.file_path}')
|
||||||
|
self.send_email()
|
||||||
|
|
||||||
|
def make_csv_file(self):
|
||||||
|
file_header = self.get_headers()
|
||||||
|
if not self.success:
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(self.file_path, 'w') as f:
|
||||||
|
file_writer = csv.writer(f, quotechar='"', quoting=csv.QUOTE_MINIMAL)
|
||||||
|
# Write headers to CSV file
|
||||||
|
file_writer.writerow(file_header)
|
||||||
|
city = None
|
||||||
|
for row in self.get_data():
|
||||||
|
row_city = row.get('city_name')
|
||||||
|
if row_city:
|
||||||
|
city = row_city
|
||||||
|
else:
|
||||||
|
row['city_name'] = city
|
||||||
|
|
||||||
|
if row.pop("node_name") == "EstablishmentNode":
|
||||||
|
file_writer.writerow(row.values())
|
||||||
|
|
@ -112,3 +112,17 @@ TESTING = sys.argv[1:2] == ['test']
|
||||||
if TESTING:
|
if TESTING:
|
||||||
ELASTICSEARCH_INDEX_NAMES = {}
|
ELASTICSEARCH_INDEX_NAMES = {}
|
||||||
ELASTICSEARCH_DSL_AUTOSYNC = False
|
ELASTICSEARCH_DSL_AUTOSYNC = False
|
||||||
|
|
||||||
|
# Email settings
|
||||||
|
SERVER_EMAIL = 'honyl@yandex.ru'
|
||||||
|
EMAIL_HOST = 'smtp.yandex.ru'
|
||||||
|
EMAIL_HOST_USER = 'honyl@yandex.ru'
|
||||||
|
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
|
||||||
|
EMAIL_PORT = '587'
|
||||||
|
EMAIL_USE_TLS = True
|
||||||
|
EMAIL_SUBJECT = 'Technical email from LunchBox'
|
||||||
|
EMAIL_FROM = 'honyl@yandex.ru'
|
||||||
|
EMAIL_TO = [
|
||||||
|
'd.kuzmenko@spider.ru',
|
||||||
|
# 'g.baranova@spider.ru'
|
||||||
|
]
|
||||||
Loading…
Reference in New Issue
Block a user