Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache user disctrict #97

Merged
merged 2 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions location/gql_mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from django.core.exceptions import ValidationError, PermissionDenied
from django.utils.translation import gettext as _
from graphene import InputObjectType
from django.core.cache import cache

import copy

from .services import LocationService, HealthFacilityService
Expand Down Expand Up @@ -155,13 +157,16 @@ def async_mutate(cls, user, **data):

@classmethod
def __delete_user_districts(cls, location: Location, location_delete_date=None):

if location_delete_date is None:
from core import datetime
location_delete_date = datetime.datetime.now()

UserDistrict.objects\
.filter(location=location, validity_to__isnull=True)\
.update(validity_to=location_delete_date)
cache.delete('user_disctrict_'+user.id)



def tree_reset_types(parent, location, new_level):
Expand Down
93 changes: 50 additions & 43 deletions location/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from functools import reduce
from django.core.cache import cache
import uuid

from core import filter_validity
Expand Down Expand Up @@ -299,56 +300,62 @@ class Meta:

@classmethod
def get_user_districts(cls, user):

"""
Retrieve the list of UserDistricts for a user, the locations are prefetched on two levels.
:param user: InteractiveUser to filter on
:return: UserDistrict *objects*
"""
if user.is_superuser is True:
return (
UserDistrict.objects
.filter(*filter_validity())
.filter(location__type='D')
)
elif user.is_imis_admin:
# TODO: Use 'distinct()' when it is supported by MSSQL or if PostgreSQL becomes the sole database.
distinct_districts_codes = UserDistrict.objects.all().values_list('location__code')
usd_list = list(set(item[0] for item in distinct_districts_codes))
user_district_ids = []
for code in usd_list:
user_district = UserDistrict.objects.filter(location__code=code).first()
user_district_ids.append(user_district.id)
return (
UserDistrict.objects
qs = cache.get('user_disctrict_'+str(user.id))
if qs:
if user.is_superuser is True:
return (
UserDistrict.objects
.filter(*filter_validity())
.filter(location__type='D')
)
elif user.is_imis_admin:
# TODO: Use 'distinct()' when it is supported by MSSQL or if PostgreSQL becomes the sole database.
distinct_districts_codes = UserDistrict.objects.all().values_list('location__code')
usd_list = list(set(item[0] for item in distinct_districts_codes))
user_district_ids = []
for code in usd_list:
user_district = UserDistrict.objects.filter(location__code=code).first()
user_district_ids.append(user_district.id)
return (
UserDistrict.objects
.filter(*filter_validity())
.filter(location__type='D')
.filter(id__in=user_district_ids)
)
if not isinstance(user, core_models.InteractiveUser):
if isinstance(user, core_models.TechnicalUser):
logger.warning(f"get_user_districts called with a technical user `{user.username}`. "
"We'll return an empty list, but it should be handled before reaching here.")
return UserDistrict.objects.none()
qs = (
UserDistrict.objects.filter(location__type='D')
.filter(location__validity_to__isnull=True)
.select_related("location")
.only(
"location__id",
"location__uuid",
"location__code",
"location__name",
"location__type",
"location__parent_id",
"location__parent__code",
)
.prefetch_related("location__parent")
.filter(user=user)
.filter(*filter_validity())
.filter(location__type='D')
.filter(id__in=user_district_ids)
)
if not isinstance(user, core_models.InteractiveUser):
if isinstance(user, core_models.TechnicalUser):
logger.warning(f"get_user_districts called with a technical user `{user.username}`. "
"We'll return an empty list, but it should be handled before reaching here.")
return UserDistrict.objects.none()
return (
UserDistrict.objects.filter(location__type='D')
.filter(location__validity_to__isnull=True)
.select_related("location")
.only(
"location__id",
"location__uuid",
"location__code",
"location__name",
"location__type",
"location__parent_id",
"location__parent__code",
.order_by("location__parent__code")
.order_by("location__code")
.exclude(location__parent__isnull=True)
)
.prefetch_related("location__parent")
.filter(user=user)
.filter(*filter_validity())
.order_by("location__parent__code")
.order_by("location__code")
.exclude(location__parent__isnull=True)
)
cache.set('user_disctrict_'+str(user.id), qs, 600)
return qs


@classmethod
def get_user_locations(cls, user):
Expand Down
Loading