|
|
|
|
@ -4,168 +4,16 @@ from io import BytesIO
|
|
|
|
|
import pandas as pd
|
|
|
|
|
from django.db.models import Q
|
|
|
|
|
from django.http import HttpResponse
|
|
|
|
|
from rest_framework import permissions, status
|
|
|
|
|
from rest_framework import status
|
|
|
|
|
from rest_framework import status as http_status
|
|
|
|
|
from rest_framework.decorators import action
|
|
|
|
|
from rest_framework.generics import GenericAPIView
|
|
|
|
|
from rest_framework.response import Response
|
|
|
|
|
from rest_framework.views import APIView
|
|
|
|
|
from rest_framework.viewsets import ReadOnlyModelViewSet
|
|
|
|
|
|
|
|
|
|
from service import serializers, models, pagination
|
|
|
|
|
from service import utils
|
|
|
|
|
from service.pagination import MyPagination
|
|
|
|
|
from service.serializers import PlacementPointSerializer
|
|
|
|
|
from service.utils import raschet as raschet_alg, load_data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def rename_result_dataset(dataframe, rename_dict, reverse=False):
|
|
|
|
|
if reverse:
|
|
|
|
|
return dataframe.rename(columns={v: k for k, v in rename_dict.items()})
|
|
|
|
|
return dataframe.rename(columns=rename_dict)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class raschet(GenericAPIView):
|
|
|
|
|
permission_classes = [permissions.AllowAny]
|
|
|
|
|
|
|
|
|
|
def post(self, request, format=None):
|
|
|
|
|
POINTS_RENAME_DICT = {
|
|
|
|
|
"point_id": "ID точки (для всех наборов одинаковые)",
|
|
|
|
|
"category": "Тип объекта",
|
|
|
|
|
"msk_ao": "Адм. округ",
|
|
|
|
|
"msk_rayon": "Адм. район",
|
|
|
|
|
"addr": "Адрес",
|
|
|
|
|
"name": "Название",
|
|
|
|
|
"model": "Модель на ML",
|
|
|
|
|
"rate": "Стандартная модель",
|
|
|
|
|
}
|
|
|
|
|
NET_RENAME_DICT = {
|
|
|
|
|
"cell_id": "ID ячейки (для всех трёх сеток - разные, нумерация сквозная)",
|
|
|
|
|
"msk_ao": "Адм. округ",
|
|
|
|
|
"msk_rayon": "Адм. район",
|
|
|
|
|
"vuz": "ВУЗы и техникумы",
|
|
|
|
|
"model": "Модель на ML",
|
|
|
|
|
"rate": "Стандартная модель",
|
|
|
|
|
}
|
|
|
|
|
TIPES_DICT = {
|
|
|
|
|
"kiosk": "городской киоск",
|
|
|
|
|
"mfc": "МФЦ",
|
|
|
|
|
"library": "библиотека",
|
|
|
|
|
"dk": "дом культуры и клуб",
|
|
|
|
|
"sport": "спортивный объект",
|
|
|
|
|
}
|
|
|
|
|
RAYONS_RENAME_DICT = {1: 'район Филёвский Парк', 2: 'район Зюзино', 3: 'район Внуково', 4: 'Алтуфьевский район',
|
|
|
|
|
5: 'Дмитровский район', 6: 'Можайский район', 7: 'район Ново-Переделкино',
|
|
|
|
|
8: 'район Щукино', 9: 'Молжаниновский район', 10: 'район Митино', 11: 'район Куркино',
|
|
|
|
|
12: 'район Аэропорт', 13: 'район Строгино', 14: 'район Крылатское',
|
|
|
|
|
15: 'район Тёплый Стан', 16: 'район Солнцево', 57: 'Бутырский район',
|
|
|
|
|
17: 'район Южное Тушино', 18: 'район Северное Тушино', 19: 'район Покровское-Стрешнево',
|
|
|
|
|
20: 'район Хорошёво-Мнёвники', 21: 'район Очаково-Матвеевское',
|
|
|
|
|
22: 'район Тропарёво-Никулино', 23: 'район Левобережный', 24: 'район Фили-Давыдково',
|
|
|
|
|
25: 'район Ховрино', 26: 'Головинский район', 27: 'район Раменки', 28: 'Войковский район',
|
|
|
|
|
29: 'район Западное Дегунино', 30: 'район Сокол', 31: 'район Проспект Вернадского',
|
|
|
|
|
32: 'район Южное Бутово', 33: 'Обручевский район', 34: 'район Ясенево',
|
|
|
|
|
35: 'район Дорогомилово', 36: 'район Коньково', 37: 'Хорошёвский район',
|
|
|
|
|
38: 'район Северный', 39: 'район Коптево', 40: 'Ломоносовский район', 58: 'район Марфино',
|
|
|
|
|
59: 'Тверской район', 41: 'Пресненский район', 74: 'район Нагатино-Садовники',
|
|
|
|
|
42: 'Бескудниковский район', 43: 'Гагаринский район', 44: 'район Черёмушки',
|
|
|
|
|
45: 'Тимирязевский район', 46: 'район Беговой', 47: 'район Хамовники',
|
|
|
|
|
48: 'район Северное Бутово', 49: 'район Лианозово', 50: 'район Восточное Дегунино',
|
|
|
|
|
51: 'Савёловский район', 52: 'Академический район', 53: 'район Чертаново Центральное',
|
|
|
|
|
54: 'район Отрадное', 55: 'район Арбат', 56: 'район Чертаново Южное',
|
|
|
|
|
60: 'район Чертаново Северное', 61: 'район Якиманка', 62: 'район Котловка',
|
|
|
|
|
63: 'Останкинский район', 64: 'Донской район', 65: 'район Бибирево',
|
|
|
|
|
66: 'район Марьина Роща', 67: 'Нагорный район', 68: 'Даниловский район',
|
|
|
|
|
73: 'район Северное Медведково', 69: 'Мещанский район', 70: 'район Бирюлёво Западное',
|
|
|
|
|
71: 'район Южное Медведково', 72: 'район Замоскворечье', 75: 'район Царицыно',
|
|
|
|
|
76: 'район Москворечье-Сабурово', 77: 'район Свиблово', 78: 'район Нагатинский Затон',
|
|
|
|
|
82: 'Таганский район', 79: 'Басманный район', 80: 'Красносельский район',
|
|
|
|
|
81: 'район Ростокино', 83: 'Алексеевский район', 84: 'район Восточный',
|
|
|
|
|
87: 'Бабушкинский район', 85: 'район Бирюлёво Восточное', 86: 'Южнопортовый район',
|
|
|
|
|
88: 'район Сокольники', 89: 'Ярославский район', 90: 'район Богородское',
|
|
|
|
|
91: 'район Метрогородок', 92: 'район Лефортово', 93: 'район Орехово-Борисово Северное',
|
|
|
|
|
94: 'район Печатники', 95: 'Лосиноостровский район', 98: 'район Новогиреево',
|
|
|
|
|
96: 'Нижегородский район', 99: 'район Марьино', 97: 'район Орехово-Борисово Южное',
|
|
|
|
|
100: 'район Преображенское', 105: 'район Братеево', 101: 'район Соколиная Гора',
|
|
|
|
|
102: 'район Перово', 103: 'район Люблино', 104: 'район Текстильщики',
|
|
|
|
|
106: 'район Зябликово', 107: 'Рязанский район', 108: 'район Измайлово',
|
|
|
|
|
109: 'район Северное Измайлово', 113: 'район Капотня', 110: 'район Кузьминки',
|
|
|
|
|
111: 'район Гольяново', 112: 'район Вешняки', 114: 'район Выхино-Жулебино',
|
|
|
|
|
115: 'район Восточное Измайлово', 118: 'район Новокосино', 116: 'район Ивановское',
|
|
|
|
|
117: 'район Косино-Ухтомский', 119: 'район Некрасовка', 120: 'район Кунцево'}
|
|
|
|
|
AO_RENAME_DICT = {1: 'Западный административный округ', 2: 'Южный административный округ',
|
|
|
|
|
3: 'Северный административный округ', 4: 'Юго-Западный административный округ',
|
|
|
|
|
5: 'Северо-Западный административный округ', 6: 'Центральный административный округ',
|
|
|
|
|
7: 'Северо-Восточный административный округ', 8: 'Юго-Восточный административный округ',
|
|
|
|
|
9: 'Восточный административный округ'}
|
|
|
|
|
EXCLUDED_COLS = ['id', 'people', 'people2025', 'stops_ot', 'routes_ot', 'in_metro', 'out_metro', 'tc', 'empls',
|
|
|
|
|
'walkers', 'schools', 'parking', 'pvz', 'gov_place', 'bike_park', 'products', 'nonprod',
|
|
|
|
|
'service', 'vuz']
|
|
|
|
|
df_points_, df_nets_ = raschet_alg(**request.data)
|
|
|
|
|
df_points_['category'] = df_points_['category'].map(TIPES_DICT)
|
|
|
|
|
df_points_['msk_ao'] = df_points_['msk_ao'].map(AO_RENAME_DICT)
|
|
|
|
|
df_points_['msk_rayon'] = df_points_['msk_rayon'].map(RAYONS_RENAME_DICT)
|
|
|
|
|
df_nets_['msk_ao'] = df_nets_['msk_ao'].map(AO_RENAME_DICT)
|
|
|
|
|
df_nets_['msk_rayon'] = df_nets_['msk_rayon'].map(RAYONS_RENAME_DICT)
|
|
|
|
|
df_points_ = df_points_.drop(columns=EXCLUDED_COLS)
|
|
|
|
|
df_nets_ = df_nets_.drop(columns=EXCLUDED_COLS)
|
|
|
|
|
|
|
|
|
|
df_points = rename_result_dataset(df_points_, POINTS_RENAME_DICT)
|
|
|
|
|
if "Стандартная модель" in df_points.columns:
|
|
|
|
|
df_points = df_points[
|
|
|
|
|
["ID точки (для всех наборов одинаковые)", "Адм. округ", "Адм. район", "Адрес", "Название",
|
|
|
|
|
"Тип объекта", "geom", "Модель на ML", "Стандартная модель"]]
|
|
|
|
|
else:
|
|
|
|
|
df_points = df_points[
|
|
|
|
|
["ID точки (для всех наборов одинаковые)", "Адм. округ", "Адм. район", "Адрес", "Название",
|
|
|
|
|
"Тип объекта", "geom", "Модель на ML", ]]
|
|
|
|
|
|
|
|
|
|
df_nets = rename_result_dataset(df_nets_, NET_RENAME_DICT)
|
|
|
|
|
if "Стандартная модель" in df_nets.columns:
|
|
|
|
|
df_nets = df_nets[
|
|
|
|
|
["ID ячейки (для всех трёх сеток - разные, нумерация сквозная)", "Адм. округ", "Адм. район", "geom",
|
|
|
|
|
"Модель на ML", "Стандартная модель"]]
|
|
|
|
|
else:
|
|
|
|
|
df_nets = df_nets[
|
|
|
|
|
["ID ячейки (для всех трёх сеток - разные, нумерация сквозная)", "Адм. округ", "Адм. район", "geom",
|
|
|
|
|
"Модель на ML"]]
|
|
|
|
|
|
|
|
|
|
with BytesIO() as b:
|
|
|
|
|
# Use the StringIO object as the filehandle.
|
|
|
|
|
writer = pd.ExcelWriter(b, engine='xlsxwriter')
|
|
|
|
|
if df_points is not None:
|
|
|
|
|
df_points.to_excel(writer, sheet_name='Точки', index=False)
|
|
|
|
|
worksheet = writer.sheets['Точки'] # pull worksheet object
|
|
|
|
|
for idx, col in enumerate(df_points): # loop through all columns
|
|
|
|
|
if col == 'geom':
|
|
|
|
|
continue
|
|
|
|
|
series = df_points[col]
|
|
|
|
|
max_len = max((
|
|
|
|
|
series.astype(str).map(len).max(), # len of largest item
|
|
|
|
|
len(str(series.name)) # len of column name/header
|
|
|
|
|
)) + 1 # adding a little extra space
|
|
|
|
|
worksheet.set_column(idx, idx, max_len)
|
|
|
|
|
if df_nets is not None:
|
|
|
|
|
df_nets.to_excel(writer, sheet_name='Полигоны', index=False)
|
|
|
|
|
worksheet = writer.sheets['Полигоны'] # pull worksheet object
|
|
|
|
|
for idx, col in enumerate(df_nets): # loop through all columns
|
|
|
|
|
if col == 'geom':
|
|
|
|
|
continue
|
|
|
|
|
series = df_nets[col]
|
|
|
|
|
max_len = max((
|
|
|
|
|
series.astype(str).map(len).max(), # len of largest item
|
|
|
|
|
len(str(series.name)) # len of column name/header
|
|
|
|
|
)) + 1 # adding a little extra space
|
|
|
|
|
worksheet.set_column(idx, idx, max_len)
|
|
|
|
|
writer.save()
|
|
|
|
|
# Set up the Http response.
|
|
|
|
|
filename = f'Выгрузка.xlsx'
|
|
|
|
|
response = HttpResponse(
|
|
|
|
|
b.getvalue(),
|
|
|
|
|
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
|
|
|
)
|
|
|
|
|
response['Content-Disposition'] = 'attachment; filename=%s' % filename
|
|
|
|
|
return response
|
|
|
|
|
from service.utils import load_data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RayonViewSet(ReadOnlyModelViewSet):
|
|
|
|
|
@ -292,106 +140,31 @@ class PlacementPointViewSet(ReadOnlyModelViewSet):
|
|
|
|
|
}
|
|
|
|
|
return Response(data, status=status.HTTP_200_OK)
|
|
|
|
|
|
|
|
|
|
@action(detail=False, methods=['get'])
|
|
|
|
|
def search_address(self, request):
|
|
|
|
|
address = self.request.GET.get('address')
|
|
|
|
|
qs = self.get_queryset()
|
|
|
|
|
qs = qs.filter(address__icontains=address)
|
|
|
|
|
|
|
|
|
|
class refresh_placement_points(APIView):
|
|
|
|
|
@staticmethod
|
|
|
|
|
def post(request):
|
|
|
|
|
warnings.filterwarnings('ignore')
|
|
|
|
|
file = request.FILES['file']
|
|
|
|
|
load_data(file)
|
|
|
|
|
return Response(status=http_status.HTTP_200_OK)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class load_ao_and_rayons(APIView):
|
|
|
|
|
@staticmethod
|
|
|
|
|
def post(request):
|
|
|
|
|
warnings.filterwarnings('ignore')
|
|
|
|
|
file_ao = request.FILES['file_ao']
|
|
|
|
|
file_rayon = request.FILES['file_rayon']
|
|
|
|
|
utils.load_ao_and_rayons(file_ao, file_rayon)
|
|
|
|
|
return Response(status=http_status.HTTP_200_OK)
|
|
|
|
|
page = self.paginate_queryset(qs)
|
|
|
|
|
if page is not None:
|
|
|
|
|
serializer = self.get_serializer(page, many=True)
|
|
|
|
|
return self.get_paginated_response(serializer.data)
|
|
|
|
|
|
|
|
|
|
serializer = self.get_serializer(qs, many=True)
|
|
|
|
|
return Response(serializer.data)
|
|
|
|
|
|
|
|
|
|
class update_status(APIView):
|
|
|
|
|
def put(self, request):
|
|
|
|
|
qs = models.PlacementPoint.objects.all()
|
|
|
|
|
@action(detail=False, methods=['put'])
|
|
|
|
|
def update_status(self, request):
|
|
|
|
|
qs = self.get_queryset()
|
|
|
|
|
new_status = self.request.GET.get('status')
|
|
|
|
|
location_ids = self.request.GET.get('location_ids[]')
|
|
|
|
|
prediction_first = self.request.GET.get('prediction_first[]')
|
|
|
|
|
prediction_current = self.request.GET.get('prediction_current[]')
|
|
|
|
|
plan_first = self.request.GET.get('plan_first[]')
|
|
|
|
|
plan_current = self.request.GET.get('plan_current[]')
|
|
|
|
|
categories = self.request.GET.get('categories[]')
|
|
|
|
|
status = self.request.GET.get('status[]')
|
|
|
|
|
delta = self.request.GET.get('delta[]')
|
|
|
|
|
fact = self.request.GET.get('fact[]')
|
|
|
|
|
age = self.request.GET.get('age[]')
|
|
|
|
|
included = self.request.GET.get('included[]')
|
|
|
|
|
excluded = self.request.GET.get('excluded[]')
|
|
|
|
|
rayons = self.request.GET.get('rayon[]')
|
|
|
|
|
aos = self.request.GET.get('ao[]')
|
|
|
|
|
if not new_status:
|
|
|
|
|
return Response({'message': 'No status provided'}, status=http_status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
if not any(
|
|
|
|
|
[location_ids, rayons, aos, prediction_first, plan_first, plan_current, prediction_current, categories,
|
|
|
|
|
status,
|
|
|
|
|
delta, fact, age]):
|
|
|
|
|
qs = models.PlacementPoint.objects.none()
|
|
|
|
|
if rayons:
|
|
|
|
|
rayons = list(rayons.split(','))
|
|
|
|
|
qs = qs.filter(rayon_id__in=rayons)
|
|
|
|
|
if aos:
|
|
|
|
|
aos = list(aos.split(','))
|
|
|
|
|
qs = qs.filter(okrug_id__in=aos)
|
|
|
|
|
if location_ids:
|
|
|
|
|
location_ids = list(location_ids.split(','))
|
|
|
|
|
qs = qs.filter(location_id__in=location_ids)
|
|
|
|
|
if prediction_first:
|
|
|
|
|
prediction_first = list(prediction_first.split(','))
|
|
|
|
|
qs = qs.filter(prediction_first__range=prediction_first)
|
|
|
|
|
if prediction_current:
|
|
|
|
|
prediction_current = list(prediction_current.split(','))
|
|
|
|
|
qs = qs.filter(prediction_current__range=prediction_current)
|
|
|
|
|
if plan_first:
|
|
|
|
|
plan_first = list(plan_first.split(','))
|
|
|
|
|
qs = qs.filter(plan_first__range=plan_first)
|
|
|
|
|
if plan_current:
|
|
|
|
|
plan_current = list(plan_current.split(','))
|
|
|
|
|
qs = qs.filter(plan_current__range=plan_current)
|
|
|
|
|
if categories:
|
|
|
|
|
categories = list(categories.split(','))
|
|
|
|
|
qs = qs.filter(category__in=categories)
|
|
|
|
|
if status:
|
|
|
|
|
status = list(status.split(','))
|
|
|
|
|
qs = qs.filter(status__in=status)
|
|
|
|
|
if delta:
|
|
|
|
|
delta = list(delta.split(','))
|
|
|
|
|
qs = qs.filter(delta__range=delta)
|
|
|
|
|
if fact:
|
|
|
|
|
fact = list(fact.split(','))
|
|
|
|
|
qs = qs.filter(fact__range=fact)
|
|
|
|
|
if age:
|
|
|
|
|
age = list(age.split(','))
|
|
|
|
|
qs = qs.filter(age__range=age)
|
|
|
|
|
if excluded:
|
|
|
|
|
excluded = list(excluded.split(','))
|
|
|
|
|
qs = qs.filter(~Q(location_id__in=excluded))
|
|
|
|
|
if included:
|
|
|
|
|
inclded = list(included.split(','))
|
|
|
|
|
qs2 = models.PlacementPoint.objects.filter(location_id__in=inclded).all()
|
|
|
|
|
qs = (qs | qs2).distinct()
|
|
|
|
|
if not any(
|
|
|
|
|
[location_ids, rayons, aos, prediction_first, plan_first, plan_current, prediction_current, categories,
|
|
|
|
|
status,
|
|
|
|
|
delta, fact, age, excluded, included]):
|
|
|
|
|
return Response({'message': 'Empty queryset'}, status=http_status.HTTP_200_OK)
|
|
|
|
|
|
|
|
|
|
return Response({'message': 'No status'}, 400)
|
|
|
|
|
qs.update(**{'status': new_status})
|
|
|
|
|
return Response({'message': 'status updated'}, status=http_status.HTTP_200_OK)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class update_fact(APIView):
|
|
|
|
|
def put(self, request):
|
|
|
|
|
@action(detail=False, methods=['put'])
|
|
|
|
|
def update_fact(self, request):
|
|
|
|
|
point_id = request.GET.get('location_id')
|
|
|
|
|
fact = request.GET.get('fact')
|
|
|
|
|
if not point_id or not fact or not fact.isdigit():
|
|
|
|
|
@ -402,67 +175,9 @@ class update_fact(APIView):
|
|
|
|
|
qs.update(**{'fact': fact})
|
|
|
|
|
return Response({'message': 'fact updated'}, status=http_status.HTTP_200_OK)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class get_excel(APIView):
|
|
|
|
|
def get(self, request):
|
|
|
|
|
qs = models.PlacementPoint.objects.all()
|
|
|
|
|
location_ids = self.request.GET.get('location_ids[]')
|
|
|
|
|
prediction_first = self.request.GET.get('prediction_first[]')
|
|
|
|
|
prediction_current = self.request.GET.get('prediction_current[]')
|
|
|
|
|
categories = self.request.GET.get('categories[]')
|
|
|
|
|
status = self.request.GET.get('status[]')
|
|
|
|
|
delta = self.request.GET.get('delta[]')
|
|
|
|
|
fact = self.request.GET.get('fact[]')
|
|
|
|
|
age = self.request.GET.get('age[]')
|
|
|
|
|
included = self.request.GET.get('included[]')
|
|
|
|
|
excluded = self.request.GET.get('excluded[]')
|
|
|
|
|
plan_first = self.request.GET.get('plan_first[]')
|
|
|
|
|
plan_current = self.request.GET.get('plan_current[]')
|
|
|
|
|
rayons = self.request.GET.get('rayon[]')
|
|
|
|
|
aos = self.request.GET.get('ao[]')
|
|
|
|
|
if location_ids:
|
|
|
|
|
location_ids = list(location_ids.split(','))
|
|
|
|
|
qs = qs.filter(location_id__in=location_ids)
|
|
|
|
|
if prediction_first:
|
|
|
|
|
prediction_first = list(prediction_first.split(','))
|
|
|
|
|
qs = qs.filter(prediction_first__range=prediction_first)
|
|
|
|
|
if prediction_current:
|
|
|
|
|
prediction_current = list(prediction_current.split(','))
|
|
|
|
|
qs = qs.filter(prediction_current__range=prediction_current)
|
|
|
|
|
if categories:
|
|
|
|
|
categories = list(categories.split(','))
|
|
|
|
|
qs = qs.filter(category__in=categories)
|
|
|
|
|
if status:
|
|
|
|
|
status = list(status.split(','))
|
|
|
|
|
qs = qs.filter(status__in=status)
|
|
|
|
|
if delta:
|
|
|
|
|
delta = list(delta.split(','))
|
|
|
|
|
qs = qs.filter(delta__range=delta)
|
|
|
|
|
if fact:
|
|
|
|
|
fact = list(fact.split(','))
|
|
|
|
|
qs = qs.filter(fact__range=fact)
|
|
|
|
|
if age:
|
|
|
|
|
age = list(age.split(','))
|
|
|
|
|
qs = qs.filter(age__range=age)
|
|
|
|
|
if plan_first:
|
|
|
|
|
plan_first = list(plan_first.split(','))
|
|
|
|
|
qs = qs.filter(plan_first__range=plan_first)
|
|
|
|
|
if rayons:
|
|
|
|
|
rayons = list(rayons.split(','))
|
|
|
|
|
qs = qs.filter(rayon_id__in=rayons)
|
|
|
|
|
if aos:
|
|
|
|
|
aos = list(aos.split(','))
|
|
|
|
|
qs = qs.filter(okrug_id__in=aos)
|
|
|
|
|
if plan_current:
|
|
|
|
|
plan_current = list(plan_current.split(','))
|
|
|
|
|
qs = qs.filter(plan_current__range=plan_current)
|
|
|
|
|
if excluded:
|
|
|
|
|
excluded = list(excluded.split(','))
|
|
|
|
|
qs = qs.filter(~Q(location_id__in=excluded))
|
|
|
|
|
if included:
|
|
|
|
|
inclded = list(included.split(','))
|
|
|
|
|
qs2 = models.PlacementPoint.objects.filter(location_id__in=inclded).all()
|
|
|
|
|
qs = (qs | qs2).distinct()
|
|
|
|
|
@action(detail=False, methods=['get'])
|
|
|
|
|
def to_excel(self, request):
|
|
|
|
|
qs = self.get_queryset()
|
|
|
|
|
data = pd.DataFrame(list(qs.values()))
|
|
|
|
|
data['start_date'] = data['start_date'].dt.tz_localize(None)
|
|
|
|
|
data['sample_trn'] = data['sample_trn'].astype(int)
|
|
|
|
|
@ -478,41 +193,31 @@ class get_excel(APIView):
|
|
|
|
|
res['Content-Disposition'] = f'attachment; filename={filename}'
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class get_top_10k(APIView):
|
|
|
|
|
def get(self, request):
|
|
|
|
|
@action(detail=False, methods=['get'])
|
|
|
|
|
def get_10k(self, request):
|
|
|
|
|
if models.PlacementPoint.objects.count() > 10000:
|
|
|
|
|
qs = models.PlacementPoint.objects.order_by('-prediction_current').all()[10000]
|
|
|
|
|
return Response({'prediction_current': qs.prediction_current}, 200)
|
|
|
|
|
return Response({'prediction_current': models.PlacementPoint.objects.order_by('prediction_current').first().prediction_current}, 200)
|
|
|
|
|
return Response(
|
|
|
|
|
{'prediction_current': models.PlacementPoint.objects.order_by(
|
|
|
|
|
'prediction_current').first().prediction_current},
|
|
|
|
|
200)
|
|
|
|
|
|
|
|
|
|
class search_address(APIView):
|
|
|
|
|
pagination_class=MyPagination
|
|
|
|
|
queryset = models.PlacementPoint.objects.all()
|
|
|
|
|
serializer_class = PlacementPointSerializer
|
|
|
|
|
@property
|
|
|
|
|
def paginator(self):
|
|
|
|
|
if not hasattr(self, '_paginator'):
|
|
|
|
|
if self.pagination_class is None:
|
|
|
|
|
self._paginator = None
|
|
|
|
|
else:
|
|
|
|
|
self._paginator = self.pagination_class()
|
|
|
|
|
return self._paginator
|
|
|
|
|
|
|
|
|
|
def paginate_queryset(self, queryset):
|
|
|
|
|
if self.paginator is None:
|
|
|
|
|
return None
|
|
|
|
|
return self.paginator.paginate_queryset(queryset, self.request, view=self)
|
|
|
|
|
class refresh_placement_points(APIView):
|
|
|
|
|
@staticmethod
|
|
|
|
|
def post(request):
|
|
|
|
|
warnings.filterwarnings('ignore')
|
|
|
|
|
file = request.FILES['file']
|
|
|
|
|
load_data(file)
|
|
|
|
|
return Response(status=http_status.HTTP_200_OK)
|
|
|
|
|
|
|
|
|
|
def get_paginated_response(self, data):
|
|
|
|
|
assert self.paginator is not None
|
|
|
|
|
return self.paginator.get_paginated_response(data)
|
|
|
|
|
def get(self, request):
|
|
|
|
|
address = self.request.GET.get('address')
|
|
|
|
|
qs = self.queryset.filter(address__icontains=address)
|
|
|
|
|
page = self.paginate_queryset(qs)
|
|
|
|
|
if page is not None:
|
|
|
|
|
serializer = self.serializer_class(page, many=True)
|
|
|
|
|
return self.get_paginated_response(serializer.data)
|
|
|
|
|
serializer = self.serializer_class(qs, many=True)
|
|
|
|
|
return Response(serializer.data)
|
|
|
|
|
|
|
|
|
|
class load_ao_and_rayons(APIView):
|
|
|
|
|
@staticmethod
|
|
|
|
|
def post(request):
|
|
|
|
|
warnings.filterwarnings('ignore')
|
|
|
|
|
file_ao = request.FILES['file_ao']
|
|
|
|
|
file_rayon = request.FILES['file_rayon']
|
|
|
|
|
utils.load_ao_and_rayons(file_ao, file_rayon)
|
|
|
|
|
return Response(status=http_status.HTTP_200_OK)
|
|
|
|
|
|