diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-09-05 20:09:46 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-09-05 20:09:46 +0200 |
commit | 6d53f660453552414207a711cef2cad2f09bf8d3 (patch) | |
tree | da14d18d48ba4c5217f466ade0aad79c40bb3bca /archaeological_operations/models.py | |
parent | 4190b4a7dc03c0b9f1ca4113b4d0706c1bfffa19 (diff) | |
parent | edfe798c15c8589933cb41314d01ff73a8d7c0c8 (diff) | |
download | Ishtar-6d53f660453552414207a711cef2cad2f09bf8d3.tar.bz2 Ishtar-6d53f660453552414207a711cef2cad2f09bf8d3.zip |
Merge branch 'master' into v0.9
Diffstat (limited to 'archaeological_operations/models.py')
-rw-r--r-- | archaeological_operations/models.py | 205 |
1 files changed, 200 insertions, 5 deletions
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index 2db101104..a855c3bda 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -22,20 +22,21 @@ from itertools import groupby from django.conf import settings from django.contrib.gis.db import models +from django.core.cache import cache from django.core.urlresolvers import reverse from django.db.models import Q, Count, Sum, Max, Avg from django.db.models.signals import post_save, m2m_changed, post_delete from django.forms import ValidationError from django.utils.translation import ugettext_lazy as _, ugettext -from ishtar_common.utils import cached_label_changed +from ishtar_common.utils import cached_label_changed, get_cache, mode from ishtar_common.models import GeneralType, BaseHistorizedItem, \ HistoricalRecords, LightHistorizedItem, OwnPerms, Department, Source,\ - Person, Organization, Town, Dashboard, IshtarUser, ValueGetter, \ + SourceType, Person, Organization, Town, Dashboard, IshtarUser, ValueGetter,\ DocumentTemplate, ShortMenuItem, DashboardFormItem, GeneralRelationType,\ GeneralRecordRelations, post_delete_record_relation, OperationType, \ - get_external_id + get_external_id, ImageModel class RemainType(GeneralType): @@ -165,13 +166,14 @@ class ClosedItem(object): return {'date': date, 'user': user} -class Operation(ClosedItem, BaseHistorizedItem, OwnPerms, ValueGetter, - ShortMenuItem, DashboardFormItem): +class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms, + ValueGetter, ShortMenuItem, DashboardFormItem): QUALITY_DICT = dict(QUALITY) SHOW_URL = 'show-operation' TABLE_COLS = ['year_index', 'operation_type', 'remains', 'towns', 'start_date', 'excavation_end_date'] TABLE_COLS.insert(4, 'associated_file_short_label') + IMAGE_PREFIX = 'operations/' creation_date = models.DateField(_(u"Creation date"), default=datetime.date.today) end_date = models.DateField(_(u"Closing date"), null=True, blank=True) @@ -459,6 +461,199 @@ class Operation(ClosedItem, BaseHistorizedItem, OwnPerms, ValueGetter, self.operation_code = self.get_available_operation_code(self.year) return super(Operation, self).save(*args, **kwargs) + @property + def nb_parcels(self): + nb = 0 + if self.associated_file: + nb = self.associated_file.parcels.count() + if not nb: + nb = self.parcels.count() + return nb + + def _get_or_set_stats(self, funcname, update): + key, val = get_cache(self.__class__, [funcname, self.pk]) + if not update and val is not None: + return val + val = getattr(self, funcname)() + cache.set(key, val, settings.CACHE_TIMEOUT) + return val + + @property + def nb_acts(self, update=False): + _(u"Number of administrative acts") + return self._get_or_set_stats('_nb_acts', update) + + def _nb_acts(self): + return self.administrative_act.count() + + @property + def nb_indexed_acts(self, update=False): + _(u"Number of indexed administrative acts") + return self._get_or_set_stats('_nb_indexed_acts', update) + + def _nb_indexed_acts(self): + return self.administrative_act.filter(act_type__indexed=True).count() + + @property + def nb_context_records(self, update=False): + _(u"Number of context records") + return self._get_or_set_stats('_nb_context_records', update) + + def _nb_context_records(self): + return self.context_record.count() + + @property + def nb_context_records_by_type(self, update=False): + return self._get_or_set_stats('_nb_context_records_by_type', update) + + def _nb_context_records_by_type(self): + nbs = [] + q = self.context_record.values( + 'unit', 'unit__label').distinct().order_by('label') + for res in q.all(): + nbs.append((unicode(res['unit__label']), + self.context_record.filter(unit=res['unit']).count())) + return nbs + + @property + def nb_context_records_by_periods(self, update=False): + return self._get_or_set_stats('_nb_context_records_by_periods', update) + + def _nb_context_records_by_periods(self): + nbs = [] + q = self.context_record.values( + 'datings__period', 'datings__period__label').distinct().order_by( + 'datings__period__order') + for res in q.all(): + nbs.append((unicode(res['datings__period__label']), + self.context_record.filter( + datings__period=res['datings__period']).count())) + return nbs + + @property + def nb_finds(self, update=False): + _(u"Number of finds") + return self._get_or_set_stats('_nb_finds', update) + + def _nb_finds(self): + from archaeological_finds.models import Find + q = Find.objects.filter( + base_finds__context_record__operation=self) + return q.count() + + @property + def nb_finds_by_material_type(self, update=False): + return self._get_or_set_stats('_nb_finds_by_material_type', update) + + def _nb_finds_by_material_type(self): + from archaeological_finds.models import Find + nbs = [] + q = Find.objects.filter( + base_finds__context_record__operation=self).values( + 'material_types__pk', 'material_types__label').distinct().order_by( + 'material_types__label') + for res in q.all(): + nbs.append( + (unicode(res['material_types__label']), + Find.objects.filter( + material_types__pk=res['material_types__pk']).count())) + return nbs + + @property + def nb_finds_by_types(self, update=False): + return self._get_or_set_stats('_nb_finds_by_types', update) + + def _nb_finds_by_types(self): + from archaeological_finds.models import Find + nbs = [] + q = Find.objects.filter( + base_finds__context_record__operation=self).values( + 'object_types', 'object_types__label').distinct().order_by( + 'object_types__label') + for res in q.all(): + label = unicode(res['object_types__label']) + if label == 'None': + label = _(u"No type") + nbs.append( + (label, + Find.objects.filter( + object_types=res['object_types']).count())) + return nbs + + @property + def nb_finds_by_periods(self, update=False): + return self._get_or_set_stats('_nb_finds_by_periods', update) + + def _nb_finds_by_periods(self): + from archaeological_finds.models import Find + nbs = [] + q = Find.objects.filter( + base_finds__context_record__operation=self).values( + 'datings__period', 'datings__period__label').distinct().order_by( + 'datings__period__order') + for res in q.all(): + nbs.append( + (unicode(res['datings__period__label']), + Find.objects.filter( + datings__period=res['datings__period']).count())) + return nbs + + @property + def nb_documents(self, update=False): + _(u"Number of sources") + return self._get_or_set_stats('_nb_documents', update) + + def _nb_documents(self): + from archaeological_context_records.models import ContextRecordSource + from archaeological_finds.models import FindSource + nbs = self.source.count() + \ + ContextRecordSource.objects.filter( + context_record__operation=self).count() + \ + FindSource.objects.filter( + find__base_finds__context_record__operation=self).count() + return nbs + + @property + def nb_documents_by_types(self, update=False): + return self._get_or_set_stats('_nb_documents_by_types', update) + + def _nb_documents_by_types(self): + from archaeological_context_records.models import ContextRecordSource + from archaeological_finds.models import FindSource + docs = {} + + qs = [ + self.source, + ContextRecordSource.objects.filter(context_record__operation=self), + FindSource.objects.filter( + find__base_finds__context_record__operation=self)] + for q in qs: + for res in q.values('source_type').distinct(): + st = res['source_type'] + if st not in docs: + docs[st] = 0 + docs[st] += q.filter(source_type=st).count() + docs = [(unicode(SourceType.objects.get(pk=k)), docs[k]) for k in docs] + return sorted(docs, key=lambda x: x[0]) + + @property + def nb_stats_finds_by_ue(self, update=False): + return self._get_or_set_stats('_nb_stats_finds_by_ue', update) + + def _nb_stats_finds_by_ue(self): + _(u"Mean") + res, finds = {}, [] + for cr in self.context_record.all(): + finds.append(cr.base_finds.count()) + if not finds: + return res + res['mean'] = float(sum(finds)) / max(len(finds), 1) + res['min'] = min(finds) + res['max'] = max(finds) + res['mode'] = u" ; ".join([str(m) for m in mode(finds)]) + return res + + m2m_changed.connect(cached_label_changed, sender=Operation.towns.through) |