diff --git a/postamates/settings.py b/postamates/settings.py index 523357e..2b2176c 100644 --- a/postamates/settings.py +++ b/postamates/settings.py @@ -181,7 +181,11 @@ SRID = 4326 CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL') CELERY_NAMESPACE = 'CELERY' PROJECT_NAME = 'postamates' -CACHE_TIMEOUT = 0 + +if DEBUG: + CACHE_TIMEOUT = 60 +else: + CACHE_TIMEOUT = 60 * 60 * 24 * 7 DEFAULT_PLACEMENT_POINT_UPDATE_RADIUS = 500 AGE_DAY_LIMIT = 270 AGE_DAY_BORDER = 30 diff --git a/service/models.py b/service/models.py index 24c1399..b7c01a1 100644 --- a/service/models.py +++ b/service/models.py @@ -1,10 +1,11 @@ from django.contrib.auth.models import User from django.contrib.gis.db import models as gis_models from django.db import models - +from django.db.models.signals import post_save, post_delete +from django.dispatch import receiver from postamates.settings import SRID from service.enums import PointStatus -from service.signals import * +from django.core.cache import cache User._meta.get_field('email')._unique = True @@ -225,3 +226,23 @@ class LastMLCall(models.Model): class TempFiles(models.Model): data = models.TextField(blank=False, null=False) + + +@receiver([post_save, post_delete], sender=Post_and_pvzCategory) +def clear_cache(sender, instance, **kwargs): + cache.clear() + + +@receiver([post_save, post_delete], sender=Post_and_pvzGroup) +def clear_cache(sender, instance, **kwargs): + cache.clear() + + +@receiver([post_save, post_delete], sender=OtherObjectsCategory) +def clear_cache(sender, instance, **kwargs): + cache.clear() + + +@receiver([post_save, post_delete], sender=OtherObjectsGroup) +def clear_cache(sender, instance, **kwargs): + cache.clear() \ No newline at end of file diff --git a/service/tasks.py b/service/tasks.py index 23941d5..ef7177a 100644 --- a/service/tasks.py +++ b/service/tasks.py @@ -22,6 +22,7 @@ from service import models from service.utils import log_to_telegram import base64 from io import StringIO +from django.core.cache import cache @shared_task() @@ -306,6 +307,7 @@ def raschet(): cursor.execute('ROLLBACK') psycopg2.extras.execute_batch(cursor, sql_update_query, update_records5) conn2.commit() + cache.clear() log_to_telegram('end raschet') @@ -357,6 +359,7 @@ def load_post_and_pvz(obj_id: int): models.PlacementPointPVZDistance.objects.create(placement_point=point, pvz_postamates_group=group, dist=post_object.distance.m) status.status = "Подсчет расстояний завершен" + cache.clear() status.save() @@ -398,6 +401,7 @@ def load_other_objects(obj_id: int): row['wkt'] = "POINT(" + lon + " " + lat + ")" models.OtherObjects.objects.get_or_create(**row) status.status = "Загрузка данных завершена" + cache.clear() status.save() diff --git a/service/utils.py b/service/utils.py index 80bfbc2..db0eaec 100644 --- a/service/utils.py +++ b/service/utils.py @@ -7,6 +7,10 @@ from geojson import MultiPolygon from service import models import requests from tqdm import tqdm +from django.core.cache import cache +from django.conf import settings +from rest_framework.response import Response +from rest_framework.viewsets import ReadOnlyModelViewSet def load_ao_and_rayons( @@ -43,3 +47,19 @@ def load_dist(filepath: str): def log_to_telegram(msg): requests.post('https://api.telegram.org/bot6275517704:AAHVp_qv9d9NU740JJdOM2fJdgS4r1AgJrw/sendMessage', json={"chat_id": "-555238820", "text": msg}) + + +def cached_func(key, func, timeout=settings.CACHE_TIMEOUT, *args, **kwargs): + d = cache.get(key) + if d is None: + d = func(*args, **kwargs) + cache.set(key, d, timeout) + return d + +class CustomReadOnlyModelViewSet(ReadOnlyModelViewSet): + def list(self, request, *args, **kwargs): + def f(): + return ReadOnlyModelViewSet.list(self, request, *args, **kwargs).data + d = cached_func(self.__class__.__name__, f) + return Response(d) + diff --git a/service/views.py b/service/views.py index 4cc9fe4..711ac52 100644 --- a/service/views.py +++ b/service/views.py @@ -28,20 +28,21 @@ from django.shortcuts import redirect from django.contrib import messages from django_filters.rest_framework import DjangoFilterBackend from rest_framework import filters +from service.utils import CustomReadOnlyModelViewSet -class AOViewSet(ReadOnlyModelViewSet): +class AOViewSet(CustomReadOnlyModelViewSet): serializer_class = serializers.AOSerializer queryset = models.AO.objects permission_classes = [AllowAny] -class PostAndPVZCategoryViewSet(ReadOnlyModelViewSet): +class PostAndPVZCategoryViewSet(CustomReadOnlyModelViewSet): serializer_class = serializers.PostAndPVZCategorySerializer queryset = models.Post_and_pvzCategory.objects -class OtherObjectsCategoryViewSet(ReadOnlyModelViewSet): +class OtherObjectsCategoryViewSet(CustomReadOnlyModelViewSet): serializer_class = serializers.OtherObjectsCategorySerializer queryset = models.OtherObjectsCategory.objects @@ -194,27 +195,31 @@ class PlacementPointViewSet(ReadOnlyModelViewSet): @action(detail=False, methods=['get']) def filters(self, request): - qs = self.get_queryset() - keys = ( - 'age_day', 'prediction_first', 'prediction_current', - 'plan_first', 'plan_current', 'fact', 'delta_first', - 'delta_current', 'flat_cnt', 'year_bld', 'levels', - 'doors', 'flats_cnt', 'popul_home', 'popul_job', - 'other_post_cnt', 'target_post_cnt', 'yndxfood_cnt', - 'yndxfood_sum', 'yndxfood_cnt_cst', - ) - temp_data = { - key: [ - x for x in list(set(qs.values_list(key, flat=True))) if - x is not None - ] - for key in keys - } - data = { - key: [ - min(temp_data[key]), max(temp_data[key]), - ] if temp_data[key] else [0, 100] for key in keys - } + def get_filter_data(): + qs = self.get_queryset() + keys = ( + 'age_day', 'prediction_first', 'prediction_current', + 'plan_first', 'plan_current', 'fact', 'delta_first', + 'delta_current', 'flat_cnt', 'year_bld', 'levels', + 'doors', 'flats_cnt', 'popul_home', 'popul_job', + 'other_post_cnt', 'target_post_cnt', 'yndxfood_cnt', + 'yndxfood_sum', 'yndxfood_cnt_cst', + ) + temp_data = { + key: [ + x for x in list(set(qs.values_list(key, flat=True))) if + x is not None + ] + for key in keys + } + data = { + key: [ + min(temp_data[key]), max(temp_data[key]), + ] if temp_data[key] else [0, 100] for key in keys + } + return data + data = utils.cached_func('get_filter_data', get_filter_data, 120) + return Response(data, status=HTTPStatus.OK) @action(detail=False, methods=['get'])