You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

213 lines
15 KiB

import json
from io import BytesIO
import pandas as pd
from django.core.cache import cache
from django.http import HttpResponse
from rest_framework import permissions
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.viewsets import ReadOnlyModelViewSet
from service import serializers, models, pagination
from service.utils import raschet as raschet_alg
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 ao_and_rayons(GenericAPIView):
permission_classes = [permissions.AllowAny]
def get(self, request, format=None):
d = cache.get('ao_and_rayons')
if d is None:
data = json.loads(open('ao_and_rayons.json', 'r').read())
cache.set('ao_and_rayons', data, 60 * 60 * 24)
d = data
return Response(d)
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
class PlacementPointViewSet(ReadOnlyModelViewSet):
serializer_class = serializers.PlacementPointSerializer
queryset = models.PlacementPoint.objects
pagination_class = pagination.MyPagination
def get_queryset(self):
qs = self.queryset.all()
location_ids = self.request.GET.get('location_ids[]')
prediction = self.request.GET.get('prediction[]')
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[]')
if location_ids:
location_ids = list(location_ids.split(','))
qs = qs.filter(location_id__in=location_ids)
if prediction:
prediction = list(prediction.split(','))
qs = qs.filter(prediction__range=prediction)
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)
return qs