rewrite_views

dev
AlexP077 3 years ago committed by Dmitry Titov
parent 2e18c5d6e9
commit 39219f7f7b

@ -9,7 +9,6 @@ from service import views
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register('', views.PlacementPointViewSet) router.register('', views.PlacementPointViewSet)
schema_view = get_schema_view( schema_view = get_schema_view(
openapi.Info( openapi.Info(
title="Snippets API", title="Snippets API",
@ -25,16 +24,8 @@ schema_view = get_schema_view(
) )
urlpatterns = [ urlpatterns = [
path('placement_points/', path('placement_points/', include([*router.urls]), name='placement_points'),
include([*router.urls, path('ao_rayons', views.AOViewSet.as_view({'get': 'list'}), name='ao_and_rayons'),
url(r'ao_rayons',views.AOViewSet.as_view({'get': 'list'}),name='ao_and_rayons'),
url(r'update_status', views.update_status.as_view(), name='update_status'),
url(r'update_fact', views.update_fact.as_view(), name='update_fact'),
url(r'to_excel', views.get_excel.as_view(), name='to_excel'),
url(r'10k', views.get_top_10k.as_view(), name='top_10_k'),
url(r'address', views.search_address.as_view(), name='search_address')
]), name='placement_points'),
path('raschet/', views.raschet.as_view(), name='ao_and_rayons'),
url(r'load_csv/', views.refresh_placement_points.as_view(), name='upload_placement_points'), url(r'load_csv/', views.refresh_placement_points.as_view(), name='upload_placement_points'),
url(r'upload_ao_and_rayons/', views.load_ao_and_rayons.as_view(), name='upload_ao_and_rayons'), url(r'upload_ao_and_rayons/', views.load_ao_and_rayons.as_view(), name='upload_ao_and_rayons'),
re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'), re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),

@ -4,168 +4,16 @@ from io import BytesIO
import pandas as pd import pandas as pd
from django.db.models import Q from django.db.models import Q
from django.http import HttpResponse 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 import status as http_status
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
from service import serializers, models, pagination from service import serializers, models, pagination
from service import utils from service import utils
from service.pagination import MyPagination from service.utils import load_data
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
class RayonViewSet(ReadOnlyModelViewSet): class RayonViewSet(ReadOnlyModelViewSet):
@ -292,106 +140,31 @@ class PlacementPointViewSet(ReadOnlyModelViewSet):
} }
return Response(data, status=status.HTTP_200_OK) 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): page = self.paginate_queryset(qs)
@staticmethod if page is not None:
def post(request): serializer = self.get_serializer(page, many=True)
warnings.filterwarnings('ignore') return self.get_paginated_response(serializer.data)
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)
serializer = self.get_serializer(qs, many=True)
return Response(serializer.data)
class update_status(APIView): @action(detail=False, methods=['put'])
def put(self, request): def update_status(self, request):
qs = models.PlacementPoint.objects.all() qs = self.get_queryset()
new_status = self.request.GET.get('status') 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: if not new_status:
return Response({'message': 'No status provided'}, status=http_status.HTTP_400_BAD_REQUEST) return Response({'message': 'No status'}, 400)
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)
qs.update(**{'status': new_status}) qs.update(**{'status': new_status})
return Response({'message': 'status updated'}, status=http_status.HTTP_200_OK) return Response({'message': 'status updated'}, status=http_status.HTTP_200_OK)
@action(detail=False, methods=['put'])
class update_fact(APIView): def update_fact(self, request):
def put(self, request):
point_id = request.GET.get('location_id') point_id = request.GET.get('location_id')
fact = request.GET.get('fact') fact = request.GET.get('fact')
if not point_id or not fact or not fact.isdigit(): if not point_id or not fact or not fact.isdigit():
@ -402,67 +175,9 @@ class update_fact(APIView):
qs.update(**{'fact': fact}) qs.update(**{'fact': fact})
return Response({'message': 'fact updated'}, status=http_status.HTTP_200_OK) return Response({'message': 'fact updated'}, status=http_status.HTTP_200_OK)
@action(detail=False, methods=['get'])
class get_excel(APIView): def to_excel(self, request):
def get(self, request): qs = self.get_queryset()
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()
data = pd.DataFrame(list(qs.values())) data = pd.DataFrame(list(qs.values()))
data['start_date'] = data['start_date'].dt.tz_localize(None) data['start_date'] = data['start_date'].dt.tz_localize(None)
data['sample_trn'] = data['sample_trn'].astype(int) data['sample_trn'] = data['sample_trn'].astype(int)
@ -478,41 +193,31 @@ class get_excel(APIView):
res['Content-Disposition'] = f'attachment; filename={filename}' res['Content-Disposition'] = f'attachment; filename={filename}'
return res return res
@action(detail=False, methods=['get'])
class get_top_10k(APIView): def get_10k(self, request):
def get(self, request): if models.PlacementPoint.objects.count() > 10000:
if models.PlacementPoint.objects.count()>10000:
qs = models.PlacementPoint.objects.order_by('-prediction_current').all()[10000] qs = models.PlacementPoint.objects.order_by('-prediction_current').all()[10000]
return Response({'prediction_current':qs.prediction_current},200) 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): class refresh_placement_points(APIView):
if self.paginator is None: @staticmethod
return None def post(request):
return self.paginator.paginate_queryset(queryset, self.request, view=self) 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 class load_ao_and_rayons(APIView):
return self.paginator.get_paginated_response(data) @staticmethod
def get(self, request): def post(request):
address = self.request.GET.get('address') warnings.filterwarnings('ignore')
qs = self.queryset.filter(address__icontains=address) file_ao = request.FILES['file_ao']
page = self.paginate_queryset(qs) file_rayon = request.FILES['file_rayon']
if page is not None: utils.load_ao_and_rayons(file_ao, file_rayon)
serializer = self.serializer_class(page, many=True) return Response(status=http_status.HTTP_200_OK)
return self.get_paginated_response(serializer.data)
serializer = self.serializer_class(qs, many=True)
return Response(serializer.data)

Loading…
Cancel
Save