diff options
Diffstat (limited to 'archaeological_context_records')
-rw-r--r-- | archaeological_context_records/admin.py | 98 | ||||
-rw-r--r-- | archaeological_context_records/forms.py | 634 | ||||
-rw-r--r-- | archaeological_context_records/ishtar_menu.py | 64 | ||||
-rw-r--r-- | archaeological_context_records/lookups.py | 11 | ||||
-rw-r--r-- | archaeological_context_records/models.py | 873 | ||||
-rw-r--r-- | archaeological_context_records/serializers.py | 146 | ||||
-rw-r--r-- | archaeological_context_records/tests.py | 662 | ||||
-rw-r--r-- | archaeological_context_records/urls.py | 205 | ||||
-rw-r--r-- | archaeological_context_records/views.py | 218 | ||||
-rw-r--r-- | archaeological_context_records/wizards.py | 90 |
10 files changed, 1721 insertions, 1280 deletions
diff --git a/archaeological_context_records/admin.py b/archaeological_context_records/admin.py index abee0a6d0..f9c8e03ff 100644 --- a/archaeological_context_records/admin.py +++ b/archaeological_context_records/admin.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2012-2015 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -32,12 +32,15 @@ from . import models class DatingAdmin(admin.ModelAdmin): - list_display = ('period', 'context_records_lbl', 'finds_lbl') - list_filter = ("period", 'dating_type', 'quality') + list_display = ("period", "context_records_lbl", "finds_lbl") + list_filter = ("period", "dating_type", "quality") model = models.Dating - search_fields = ['context_records__cached_label', 'period__label', - 'find__cached_label'] - readonly_fields = ['context_records_lbl', 'finds_lbl'] + search_fields = [ + "context_records__cached_label", + "period__label", + "find__cached_label", + ] + readonly_fields = ["context_records_lbl", "finds_lbl"] admin_site.register(models.Dating, DatingAdmin) @@ -47,27 +50,32 @@ class AdminContextRecordForm(forms.ModelForm): class Meta: model = models.ContextRecord exclude = [] - point_2d = PointField(label=_("Point"), required=False, - widget=OSMWidget) - multi_polygon = MultiPolygonField(label=_("Multi polygon"), required=False, - widget=OSMWidget) - operation = AutoCompleteSelectField('operation') - parcel = AutoCompleteSelectField('parcel', required=False) - town = AutoCompleteSelectField('town', required=False) - archaeological_site = AutoCompleteSelectField('archaeological_site', - required=False) - lock_user = AutoCompleteSelectField('user', required=False) + + point_2d = PointField(label=_("Point"), required=False, widget=OSMWidget) + multi_polygon = MultiPolygonField( + label=_("Multi polygon"), required=False, widget=OSMWidget + ) + operation = AutoCompleteSelectField("operation") + parcel = AutoCompleteSelectField("parcel", required=False) + town = AutoCompleteSelectField("town", required=False) + archaeological_site = AutoCompleteSelectField("archaeological_site", required=False) + lock_user = AutoCompleteSelectField("user", required=False) class ContextRecordAdmin(HistorizedObjectAdmin): - list_display = ('label', 'operation', 'parcel') - list_filter = ('unit',) - search_fields = ('label', 'parcel__operation__cached_label', - 'parcel__section', 'parcel__parcel_number') + list_display = ("label", "operation", "parcel") + list_filter = ("unit",) + search_fields = ( + "label", + "parcel__operation__cached_label", + "parcel__section", + "parcel__parcel_number", + ) model = models.ContextRecord form = AdminContextRecordForm readonly_fields = HistorizedObjectAdmin.readonly_fields + [ - 'cached_label', 'datings' + "cached_label", + "datings", ] exclude = ["documents", "main_image"] @@ -76,44 +84,58 @@ admin_site.register(models.ContextRecord, ContextRecordAdmin) class RecordRelationsAdmin(admin.ModelAdmin): - list_display = ('left_record', 'relation_type', 'right_record') - list_filter = ('relation_type',) + list_display = ("left_record", "relation_type", "right_record") + list_filter = ("relation_type",) model = models.RecordRelations - form = make_ajax_form(model, { - 'left_record': 'context_record', - 'right_record': 'context_record', - }) + form = make_ajax_form( + model, + { + "left_record": "context_record", + "right_record": "context_record", + }, + ) admin_site.register(models.RecordRelations, RecordRelationsAdmin) class RelationTypeAdmin(GeneralTypeAdmin): - list_display = ('label', 'txt_idx', 'tiny_label', 'available', - 'symmetrical', 'logical_relation', 'inverse_relation', - 'order', 'comment') + list_display = ( + "label", + "txt_idx", + "tiny_label", + "available", + "symmetrical", + "logical_relation", + "inverse_relation", + "order", + "comment", + ) admin_site.register(models.RelationType, RelationTypeAdmin) class UnitAdmin(GeneralTypeAdmin): - list_display = ['label', 'txt_idx', 'parent', 'available', 'order', - 'comment'] + list_display = ["label", "txt_idx", "parent", "available", "order", "comment"] + admin_site.register(models.Unit, UnitAdmin) - + class IdentificationTypeAdmin(GeneralTypeAdmin): - list_display = ['label', 'txt_idx', 'available', 'order', 'comment'] + list_display = ["label", "txt_idx", "available", "order", "comment"] + admin_site.register(models.IdentificationType, IdentificationTypeAdmin) general_models = [ - models.DatingType, models.DatingQuality, models.DocumentationType, - models.ActivityType, models.ExcavationTechnicType] + models.DatingType, + models.DatingQuality, + models.DocumentationType, + models.ActivityType, + models.ExcavationTechnicType, +] for model in general_models: admin_site.register(model, GeneralTypeAdmin) - - diff --git a/archaeological_context_records/forms.py b/archaeological_context_records/forms.py index c4fa6f8fe..d727dae27 100644 --- a/archaeological_context_records/forms.py +++ b/archaeological_context_records/forms.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -29,19 +29,45 @@ from django.core import validators from django.forms.formsets import formset_factory from ishtar_common.utils import ugettext_lazy as _ -from ishtar_common.models import valid_id, IshtarSiteProfile, Town, \ - SpatialReferenceSystem, valid_ids +from ishtar_common.models import ( + valid_id, + IshtarSiteProfile, + Town, + SpatialReferenceSystem, + valid_ids, +) from archaeological_context_records import models -from ishtar_common.forms import FinalForm, FormSet, \ - reverse_lazy, get_form_selection, ManageOldType, CustomForm, \ - FieldType, CustomFormSearch, IshtarForm, FormHeader, HistorySelect, \ - MultiSearchForm, LockForm, DocumentItemSelect +from ishtar_common.forms import ( + FinalForm, + FormSet, + reverse_lazy, + get_form_selection, + ManageOldType, + CustomForm, + FieldType, + CustomFormSearch, + IshtarForm, + FormHeader, + HistorySelect, + MultiSearchForm, + LockForm, + DocumentItemSelect, +) from ishtar_common.forms_common import get_town_field -from archaeological_operations.forms import OperationSelect, ParcelField, \ - RecordRelationsForm as OpeRecordRelationsForm, RecordRelationsFormSetBase -from archaeological_operations.models import Period, Parcel, Operation, \ - ArchaeologicalSite, RelationType as OpeRelationType +from archaeological_operations.forms import ( + OperationSelect, + ParcelField, + RecordRelationsForm as OpeRecordRelationsForm, + RecordRelationsFormSetBase, +) +from archaeological_operations.models import ( + Period, + Parcel, + Operation, + ArchaeologicalSite, + RelationType as OpeRelationType, +) from archaeological_operations.widgets import OAWidget from bootstrap_datepicker.widgets import DatePicker from ishtar_common import widgets @@ -51,46 +77,48 @@ class OperationFormSelection(CustomForm, forms.Form): form_label = _("Operation") form_admin_name = _("Context record - 010 - Operation choice") form_slug = "contextrecord-010-operationchoice" - associated_models = {'operation': Operation} - currents = {'operation': Operation} + associated_models = {"operation": Operation} + currents = {"operation": Operation} operation = forms.IntegerField( - label=_("Operation"), required=False, + label=_("Operation"), + required=False, widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-operation'), - associated_model=Operation), - validators=[valid_id(Operation)]) + reverse_lazy("autocomplete-operation"), associated_model=Operation + ), + validators=[valid_id(Operation)], + ) class PeriodSelect(forms.Form): - datings__period = forms.ChoiceField(label=_("Dating - period"), - choices=[]) - datings__precise_dating = forms.CharField( - label=_("Dating - precise")) + datings__period = forms.ChoiceField(label=_("Dating - period"), choices=[]) + datings__precise_dating = forms.CharField(label=_("Dating - precise")) datings__start_date__before = forms.IntegerField( - label=_("Dating - start date before")) + label=_("Dating - start date before") + ) datings__start_date__after = forms.IntegerField( - label=_("Dating - start date after")) - datings__end_date__before = forms.IntegerField( - label=_("Dating - end date before")) - datings__end_date__after = forms.IntegerField( - label=_("Dating - end date after")) - datings__dating_type = forms.ChoiceField(label=_("Dating - dating type"), - choices=[]) - datings__quality = forms.ChoiceField(label=_("Dating - dating quality"), - choices=[]) + label=_("Dating - start date after") + ) + datings__end_date__before = forms.IntegerField(label=_("Dating - end date before")) + datings__end_date__after = forms.IntegerField(label=_("Dating - end date after")) + datings__dating_type = forms.ChoiceField( + label=_("Dating - dating type"), choices=[] + ) + datings__quality = forms.ChoiceField(label=_("Dating - dating quality"), choices=[]) TYPES = [ - FieldType('datings__period', Period), - FieldType('datings__dating_type', models.DatingType), - FieldType('datings__quality', models.DatingQuality), + FieldType("datings__period", Period), + FieldType("datings__dating_type", models.DatingType), + FieldType("datings__quality", models.DatingQuality), + ] + PERIOD_FIELDS = [ + "datings__period", + "datings__precise_dating", + "datings__start_date__before", + "datings__start_date__after", + "datings__end_date__before", + "datings__end_date__after", + "datings__dating_type", + "datings__quality", ] - PERIOD_FIELDS = ["datings__period", - "datings__precise_dating", - "datings__start_date__before", - "datings__start_date__after", - "datings__end_date__before", - "datings__end_date__after", - "datings__dating_type", - "datings__quality"] def _reorder_period_fields(self, insert_period_after): fields = OrderedDict() @@ -110,37 +138,41 @@ class RecordSelect(DocumentItemSelect, PeriodSelect): form_slug = "contextrecord-001-search" search_vector = forms.CharField( - label=_("Full text search"), widget=widgets.SearchWidget( - 'archaeological-context-records', 'contextrecord' - )) + label=_("Full text search"), + widget=widgets.SearchWidget("archaeological-context-records", "contextrecord"), + ) label = forms.CharField(label=_("ID"), max_length=100) town = get_town_field() - if settings.COUNTRY == 'fr': + if settings.COUNTRY == "fr": operation__code_patriarche = forms.CharField( - max_length=500, - widget=OAWidget, - label=_("Code PATRIARCHE")) + max_length=500, widget=OAWidget, label=_("Code PATRIARCHE") + ) operation__year = forms.IntegerField(label=_("Operation's year")) operation__operation_code = forms.IntegerField( - label=_("Operation's number (index by year)")) + label=_("Operation's number (index by year)") + ) archaeological_site = forms.IntegerField( label=_("Archaeological site"), widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-archaeologicalsite'), - associated_model=ArchaeologicalSite), - validators=[valid_id(ArchaeologicalSite)]) + reverse_lazy("autocomplete-archaeologicalsite"), + associated_model=ArchaeologicalSite, + ), + validators=[valid_id(ArchaeologicalSite)], + ) ope_relation_types = forms.ChoiceField( - label=_("Search within related operations"), choices=[]) + label=_("Search within related operations"), choices=[] + ) unit = forms.ChoiceField(label=_("Unit type"), choices=[]) parcel = forms.CharField(label=_("Parcel")) has_finds = forms.NullBooleanField(label=_("Has finds")) cr_relation_types = forms.ChoiceField( - label=_("Search within relations"), choices=[]) + label=_("Search within relations"), choices=[] + ) TYPES = PeriodSelect.TYPES + [ - FieldType('unit', models.Unit), - FieldType('cr_relation_types', models.RelationType), - FieldType('ope_relation_types', OpeRelationType), + FieldType("unit", models.Unit), + FieldType("cr_relation_types", models.RelationType), + FieldType("ope_relation_types", OpeRelationType), ] SITE_KEYS = {"archaeological_site": None} @@ -150,48 +182,58 @@ class RecordSelect(DocumentItemSelect, PeriodSelect): def get_input_ids(self): ids = super(RecordSelect, self).get_input_ids() - if 'cr_relation_types' in ids: - ids.pop(ids.index('cr_relation_types')) - for idx, c in enumerate(self.fields['cr_relation_types'].choices): - ids.append('cr_relation_types_{}'.format(idx)) - if 'ope_relation_types' in ids: - ids.pop(ids.index('ope_relation_types')) - for idx, c in enumerate(self.fields['ope_relation_types'].choices): - ids.append('ope_relation_types_{}'.format(idx)) + if "cr_relation_types" in ids: + ids.pop(ids.index("cr_relation_types")) + for idx, c in enumerate(self.fields["cr_relation_types"].choices): + ids.append("cr_relation_types_{}".format(idx)) + if "ope_relation_types" in ids: + ids.pop(ids.index("ope_relation_types")) + for idx, c in enumerate(self.fields["ope_relation_types"].choices): + ids.append("ope_relation_types_{}".format(idx)) return ids class RecordFormSelection(LockForm, CustomFormSearch): SEARCH_AND_SELECT = True form_label = _("Context record search") - pk_key = 'pk' - associated_models = {'pk': models.ContextRecord} - currents = {'pk': models.ContextRecord} + pk_key = "pk" + associated_models = {"pk": models.ContextRecord} + currents = {"pk": models.ContextRecord} pk = forms.IntegerField( - label="", required=False, + label="", + required=False, widget=widgets.DataTable( - reverse_lazy('get-contextrecord'), - RecordSelect, models.ContextRecord, - gallery=True, map=True, - source_full=reverse_lazy('get-contextrecord-full')), - validators=[valid_id(models.ContextRecord)]) + reverse_lazy("get-contextrecord"), + RecordSelect, + models.ContextRecord, + gallery=True, + map=True, + source_full=reverse_lazy("get-contextrecord-full"), + ), + validators=[valid_id(models.ContextRecord)], + ) class RecordFormMultiSelection(LockForm, MultiSearchForm): form_label = _("Context record search") - associated_models = {'pks': models.ContextRecord} - pk_key = 'pks' + associated_models = {"pks": models.ContextRecord} + pk_key = "pks" pk = forms.CharField( - label="", required=False, + label="", + required=False, widget=widgets.DataTable( - reverse_lazy('get-contextrecord'), - RecordSelect, models.ContextRecord, + reverse_lazy("get-contextrecord"), + RecordSelect, + models.ContextRecord, multiple_select=True, - gallery=True, map=True, - source_full=reverse_lazy('get-contextrecord-full')), - validators=[valid_ids(models.ContextRecord)]) + gallery=True, + map=True, + source_full=reverse_lazy("get-contextrecord-full"), + ), + validators=[valid_ids(models.ContextRecord)], + ) def get_init_parcel(form, operation, prefix=""): @@ -199,23 +241,26 @@ def get_init_parcel(form, operation, prefix=""): sort = lambda x: (x.town.name, x.section) parcels = sorted(parcels, key=sort) for key, gparcels in groupby(parcels, sort): - form.fields[prefix + 'parcel'].choices.append( + form.fields[prefix + "parcel"].choices.append( ( " - ".join(k for k in key if k), [(parcel.pk, parcel.short_label) for parcel in gparcels], ) ) - if len(form.fields[prefix + 'parcel'].choices) == 1 and \ - (prefix + 'town') in form.fields: + if ( + len(form.fields[prefix + "parcel"].choices) == 1 + and (prefix + "town") in form.fields + ): # only the empty choice is available - form.fields.pop(prefix + 'parcel') - form.fields[prefix + 'town'].required = True - if (prefix + 'town') in form.fields: - if form.fields[prefix + 'town'].required: - form.fields[prefix + 'town'].choices = [] # remove the empty choice - form.fields[prefix + 'town'].choices += [ - (t.pk, str(t)) for t in operation.towns.all()] + form.fields.pop(prefix + "parcel") + form.fields[prefix + "town"].required = True + if (prefix + "town") in form.fields: + if form.fields[prefix + "town"].required: + form.fields[prefix + "town"].choices = [] # remove the empty choice + form.fields[prefix + "town"].choices += [ + (t.pk, str(t)) for t in operation.towns.all() + ] class RecordFormGeneral(CustomForm, ManageOldType): @@ -226,96 +271,122 @@ class RecordFormGeneral(CustomForm, ManageOldType): file_upload = True base_models = ["documentation"] associated_models = { - 'archaeological_site': ArchaeologicalSite, - 'parcel': Parcel, 'unit': models.Unit, 'town': Town, - 'documentation': models.DocumentationType, - 'spatial_reference_system': SpatialReferenceSystem, - 'excavation_technic': models.ExcavationTechnicType} + "archaeological_site": ArchaeologicalSite, + "parcel": Parcel, + "unit": models.Unit, + "town": Town, + "documentation": models.DocumentationType, + "spatial_reference_system": SpatialReferenceSystem, + "excavation_technic": models.ExcavationTechnicType, + } pk = forms.IntegerField(required=False, widget=forms.HiddenInput) operation_id = forms.IntegerField(widget=forms.HiddenInput) parcel = forms.ChoiceField(label=_("Parcel"), choices=[]) town = forms.ChoiceField(label=_("Town"), choices=[], required=False) archaeological_site = forms.ChoiceField( - label=" ", choices=[], required=False, - help_text=_("Only the items associated to the operation can be " - "selected.") - ) - label = forms.CharField(label=_("ID"), - validators=[validators.MaxLengthValidator(200)]) - unit = forms.ChoiceField(label=_("Context record type"), required=False, - choices=[]) - description = forms.CharField(label=_("Description"), - widget=forms.Textarea, required=False) - comment = forms.CharField(label=_("General comment"), - widget=forms.Textarea, required=False) + label=" ", + choices=[], + required=False, + help_text=_("Only the items associated to the operation can be " "selected."), + ) + label = forms.CharField( + label=_("ID"), validators=[validators.MaxLengthValidator(200)] + ) + unit = forms.ChoiceField(label=_("Context record type"), required=False, choices=[]) + description = forms.CharField( + label=_("Description"), widget=forms.Textarea, required=False + ) + comment = forms.CharField( + label=_("General comment"), widget=forms.Textarea, required=False + ) excavation_technic = forms.ChoiceField( - label=_("Excavation technique"), choices=[], required=False) + label=_("Excavation technique"), choices=[], required=False + ) surface = forms.IntegerField( - required=False, widget=widgets.AreaWidget, + required=False, + widget=widgets.AreaWidget, label=_("Total surface (m2)"), - validators=[validators.MinValueValidator(0), - validators.MaxValueValidator(999999999)]) + validators=[ + validators.MinValueValidator(0), + validators.MaxValueValidator(999999999), + ], + ) length = forms.FloatField(label=_("Length (m)"), required=False) width = forms.FloatField(label=_("Width (m)"), required=False) thickness = forms.FloatField(label=_("Thickness (m)"), required=False) diameter = forms.FloatField(label=_("Diameter (m)"), required=False) depth = forms.FloatField(label=_("Depth (m)"), required=False) depth_of_appearance = forms.FloatField( - label=_("Depth of appearance (m)"), required=False) - opening_date = forms.DateField(label=_("Opening date"), - widget=DatePicker, required=False) - closing_date = forms.DateField(label=_("Closing date"), - widget=DatePicker, required=False) + label=_("Depth of appearance (m)"), required=False + ) + opening_date = forms.DateField( + label=_("Opening date"), widget=DatePicker, required=False + ) + closing_date = forms.DateField( + label=_("Closing date"), widget=DatePicker, required=False + ) documentation = forms.MultipleChoiceField( - label=_("Documentation"), choices=[], required=False, - widget=widgets.Select2Multiple) + label=_("Documentation"), + choices=[], + required=False, + widget=widgets.Select2Multiple, + ) location = forms.CharField( - label=_("Location"), widget=forms.Textarea, - required=False, validators=[validators.MaxLengthValidator(200)]) + label=_("Location"), + widget=forms.Textarea, + required=False, + validators=[validators.MaxLengthValidator(200)], + ) - HEADERS['x'] = FormHeader(_("Coordinates")) + HEADERS["x"] = FormHeader(_("Coordinates")) x = forms.FloatField(label=_("X"), required=False) - estimated_error_x = forms.FloatField(label=_("Estimated error for X"), - required=False) + estimated_error_x = forms.FloatField( + label=_("Estimated error for X"), required=False + ) y = forms.FloatField(label=_("Y"), required=False) - estimated_error_y = forms.FloatField(label=_("Estimated error for Y"), - required=False) + estimated_error_y = forms.FloatField( + label=_("Estimated error for Y"), required=False + ) z = forms.FloatField(label=_("Z"), required=False) - estimated_error_z = forms.FloatField(label=_("Estimated error for Z"), - required=False) + estimated_error_z = forms.FloatField( + label=_("Estimated error for Z"), required=False + ) spatial_reference_system = forms.ChoiceField( - label=_("Spatial Reference System"), required=False, choices=[]) + label=_("Spatial Reference System"), required=False, choices=[] + ) TYPES = [ - FieldType('unit', models.Unit), - FieldType('excavation_technic', models.ExcavationTechnicType), - FieldType('documentation', models.DocumentationType, is_multiple=True), - FieldType('spatial_reference_system', SpatialReferenceSystem), + FieldType("unit", models.Unit), + FieldType("excavation_technic", models.ExcavationTechnicType), + FieldType("documentation", models.DocumentationType, is_multiple=True), + FieldType("spatial_reference_system", SpatialReferenceSystem), ] PROFILE_FILTER = { - 'mapping': [ - 'x', - 'y', - 'z', - 'estimated_error_x', - 'estimated_error_y', - 'estimated_error_z', - 'spatial_reference_system' + "mapping": [ + "x", + "y", + "z", + "estimated_error_x", + "estimated_error_y", + "estimated_error_z", + "spatial_reference_system", ], } def __init__(self, *args, **kwargs): # TODO: simplify operation = None - if 'data' in kwargs and kwargs['data'] and \ - ('operation' in kwargs['data'] or - 'context_record' in kwargs['data']): - if 'operation' in kwargs['data']: - operation = kwargs['data'].pop('operation') + if ( + "data" in kwargs + and kwargs["data"] + and ("operation" in kwargs["data"] or "context_record" in kwargs["data"]) + ): + if "operation" in kwargs["data"]: + operation = kwargs["data"].pop("operation") if type(operation) in (list, tuple): operation = operation[0] - if not hasattr(operation, 'id'): + if not hasattr(operation, "id"): operation_id = operation try: operation = Operation.objects.get(pk=operation_id) @@ -323,42 +394,43 @@ class RecordFormGeneral(CustomForm, ManageOldType): operation = None # force operation modification # if posted - if operation and kwargs['data']: - if hasattr(operation, 'id'): - kwargs['data'][kwargs['prefix'] + '-operation_id'] = \ - operation.id + if operation and kwargs["data"]: + if hasattr(operation, "id"): + kwargs["data"][ + kwargs["prefix"] + "-operation_id" + ] = operation.id else: - kwargs['data'][kwargs['prefix'] + '-operation_id'] = \ - operation - if 'context_record' in kwargs['data'] and \ - kwargs['data']['context_record']: - operation = kwargs['data']['context_record'].operation + kwargs["data"][kwargs["prefix"] + "-operation_id"] = operation + if "context_record" in kwargs["data"] and kwargs["data"]["context_record"]: + operation = kwargs["data"]["context_record"].operation # clean data if not "real" data # prefix_value = kwargs['prefix'] - if not [k for k in kwargs['data'].keys() - if k.startswith(kwargs['prefix']) and kwargs['data'][k]]: - kwargs['data'] = None - if 'files' in kwargs: - kwargs.pop('files') + if not [ + k + for k in kwargs["data"].keys() + if k.startswith(kwargs["prefix"]) and kwargs["data"][k] + ]: + kwargs["data"] = None + if "files" in kwargs: + kwargs.pop("files") super(RecordFormGeneral, self).__init__(*args, **kwargs) profile = IshtarSiteProfile.get_current_profile() - self.fields['parcel'].choices = [('', '--')] + self.fields["parcel"].choices = [("", "--")] if not profile.parcel_mandatory: - self.fields['parcel'].required = False - self.fields['town'].choices = [('', '--')] + self.fields["parcel"].required = False + self.fields["town"].choices = [("", "--")] else: - self.fields.pop('town') + self.fields.pop("town") site_label = IshtarSiteProfile.get_default_site_label() - self.fields['archaeological_site'].label = site_label - self.fields['archaeological_site'].choices = [('', '--')] + self.fields["archaeological_site"].label = site_label + self.fields["archaeological_site"].choices = [("", "--")] if operation: - self.fields['operation_id'].initial = operation.pk + self.fields["operation_id"].initial = operation.pk get_init_parcel(self, operation) - self.fields['archaeological_site'].choices += [ - (site.pk, str(site)) - for site in operation.archaeological_sites.all() + self.fields["archaeological_site"].choices += [ + (site.pk, str(site)) for site in operation.archaeological_sites.all() ] def clean(self): @@ -367,43 +439,44 @@ class RecordFormGeneral(CustomForm, ManageOldType): operation_id = cleaned_data.get("operation_id") label = cleaned_data.get("label") cr = models.ContextRecord.objects.filter( - label=label, parcel__operation__pk=operation_id) - if 'pk' in cleaned_data and cleaned_data['pk']: - cr = cr.exclude(pk=int(cleaned_data['pk'])) + label=label, parcel__operation__pk=operation_id + ) + if "pk" in cleaned_data and cleaned_data["pk"]: + cr = cr.exclude(pk=int(cleaned_data["pk"])) if cr.count(): - raise forms.ValidationError(_("This ID already exists for " - "this operation.")) - if not self.cleaned_data.get('parcel', None) and not \ - self.cleaned_data.get('town', None): - raise forms.ValidationError(_("You have to choose a town or a " - "parcel.")) + raise forms.ValidationError( + _("This ID already exists for " "this operation.") + ) + if not self.cleaned_data.get("parcel", None) and not self.cleaned_data.get( + "town", None + ): + raise forms.ValidationError(_("You have to choose a town or a " "parcel.")) return cleaned_data class DatingForm(ManageOldType, forms.Form): form_label = _("Dating") - base_model = 'dating' - associated_models = {'dating_type': models.DatingType, - 'quality': models.DatingQuality, - 'period': models.Period} + base_model = "dating" + associated_models = { + "dating_type": models.DatingType, + "quality": models.DatingQuality, + "period": models.Period, + } period = forms.ChoiceField(label=_("Period"), choices=[]) start_date = forms.IntegerField(label=_("Start date"), required=False) end_date = forms.IntegerField(label=_("End date"), required=False) quality = forms.ChoiceField(label=_("Quality"), required=False, choices=[]) - dating_type = forms.ChoiceField(label=_("Dating type"), required=False, - choices=[]) - precise_dating = forms.CharField(label=_("Precise dating"), - required=False) + dating_type = forms.ChoiceField(label=_("Dating type"), required=False, choices=[]) + precise_dating = forms.CharField(label=_("Precise dating"), required=False) TYPES = [ - FieldType('dating_type', models.DatingType), - FieldType('quality', models.DatingQuality), - FieldType('period', models.Period) + FieldType("dating_type", models.DatingType), + FieldType("quality", models.DatingQuality), + FieldType("period", models.Period), ] -DatingFormSet = formset_factory(DatingForm, can_delete=True, - formset=FormSet) +DatingFormSet = formset_factory(DatingForm, can_delete=True, formset=FormSet) DatingFormSet.form_label = _("Dating") DatingFormSet.form_admin_name = _("Context record - 030 - Dating") DatingFormSet.form_slug = "contextrecord-030-datings" @@ -412,25 +485,29 @@ DatingFormSet.form_slug = "contextrecord-030-datings" class RecordRelationsForm(OpeRecordRelationsForm): current_model = models.RelationType current_related_model = models.ContextRecord - associated_models = {'right_record': models.ContextRecord, - 'relation_type': models.RelationType} + associated_models = { + "right_record": models.ContextRecord, + "relation_type": models.RelationType, + } right_record = forms.ChoiceField( - label=_("Context record"), choices=[], required=False) + label=_("Context record"), choices=[], required=False + ) def __init__(self, *args, **kwargs): crs = None - if 'data' in kwargs and 'CONTEXT_RECORDS' in kwargs['data']: - crs = kwargs['data']['CONTEXT_RECORDS'] + if "data" in kwargs and "CONTEXT_RECORDS" in kwargs["data"]: + crs = kwargs["data"]["CONTEXT_RECORDS"] super(RecordRelationsForm, self).__init__(*args, **kwargs) - self.fields['relation_type'].choices = \ - models.RelationType.get_types( - initial=self.init_data.get('relation_type')) + self.fields["relation_type"].choices = models.RelationType.get_types( + initial=self.init_data.get("relation_type") + ) if crs: - self.fields['right_record'].choices = [('', '-' * 2)] + crs + self.fields["right_record"].choices = [("", "-" * 2)] + crs RecordRelationsFormSet = formset_factory( - RecordRelationsForm, can_delete=True, formset=RecordRelationsFormSetBase) + RecordRelationsForm, can_delete=True, formset=RecordRelationsFormSetBase +) RecordRelationsFormSet.form_label = _("Relations") RecordRelationsFormSet.form_admin_name = _("Context record - 050 - Relations") RecordRelationsFormSet.form_slug = "contextrecord-050-recordrelations" @@ -441,36 +518,41 @@ class RecordFormInterpretation(CustomForm, ManageOldType, forms.Form): form_admin_name = _("Context record - 040 - Interpretation") form_slug = "contextrecord-040-interpretation" - associated_models = {'activity': models.ActivityType, - 'identification': models.IdentificationType} + associated_models = { + "activity": models.ActivityType, + "identification": models.IdentificationType, + } datings_comment = forms.CharField( - label=_("Comments on dating"), required=False, - widget=forms.Textarea) - filling = forms.CharField(label=_("Filling"), - widget=forms.Textarea, required=False) - interpretation = forms.CharField(label=_("Interpretation"), - widget=forms.Textarea, required=False) - activity = forms.ChoiceField(label=_("Activity"), required=False, - choices=[]) - identification = forms.ChoiceField(label=_("Identification"), - required=False, choices=[]) + label=_("Comments on dating"), required=False, widget=forms.Textarea + ) + filling = forms.CharField(label=_("Filling"), widget=forms.Textarea, required=False) + interpretation = forms.CharField( + label=_("Interpretation"), widget=forms.Textarea, required=False + ) + activity = forms.ChoiceField(label=_("Activity"), required=False, choices=[]) + identification = forms.ChoiceField( + label=_("Identification"), required=False, choices=[] + ) taq = forms.IntegerField(label=_("TAQ"), required=False) - taq_estimated = forms.IntegerField(label=_("Estimated TAQ"), - required=False) + taq_estimated = forms.IntegerField(label=_("Estimated TAQ"), required=False) tpq = forms.IntegerField(label=_("TPQ"), required=False) - tpq_estimated = forms.IntegerField(label=_("Estimated TPQ"), - required=False) + tpq_estimated = forms.IntegerField(label=_("Estimated TPQ"), required=False) TYPES = [ - FieldType('activity', models.ActivityType), - FieldType('identification', models.IdentificationType), + FieldType("activity", models.ActivityType), + FieldType("identification", models.IdentificationType), ] OperationRecordFormSelection = get_form_selection( - 'OperationRecordFormSelection', _("Operation search"), 'operation_id', - Operation, OperationSelect, 'get-operation', - _("You should select an operation.")) + "OperationRecordFormSelection", + _("Operation search"), + "operation_id", + Operation, + OperationSelect, + "get-operation", + _("You should select an operation."), +) class RecordDeletionForm(FinalForm): @@ -481,30 +563,31 @@ class RecordDeletionForm(FinalForm): class QAOperationCR(IshtarForm): town = forms.ChoiceField(label=_("Town"), choices=[]) archaeological_site = forms.ChoiceField( - label=" ", choices=[], required=False, - help_text=_("Only the items associated to the operation can be " - "selected.") + label=" ", + choices=[], + required=False, + help_text=_("Only the items associated to the operation can be " "selected."), + ) + label = forms.CharField( + label=_("ID"), validators=[validators.MaxLengthValidator(200)] ) - label = forms.CharField(label=_("ID"), - validators=[validators.MaxLengthValidator(200)]) parcel = forms.ChoiceField(label=_("Parcel"), choices=[], required=False) - unit = forms.ChoiceField(label=_("Context record type"), required=False, - choices=[]) + unit = forms.ChoiceField(label=_("Context record type"), required=False, choices=[]) TYPES = [ - FieldType('unit', models.Unit), + FieldType("unit", models.Unit), ] def __init__(self, *args, **kwargs): - self.items = kwargs.pop('items') + self.items = kwargs.pop("items") super(QAOperationCR, self).__init__(*args, **kwargs) self.profil = IshtarSiteProfile.get_current_profile() site_label = self.profil.get_site_label() - self.fields['archaeological_site'].label = site_label - self.fields['archaeological_site'].choices = [('', '--')] + self.fields["archaeological_site"].label = site_label + self.fields["archaeological_site"].choices = [("", "--")] if self.profil.parcel_mandatory: - self.fields['parcel'].required = True - self.fields.pop('town') + self.fields["parcel"].required = True + self.fields.pop("town") else: self.fields.pop("parcel") @@ -512,31 +595,30 @@ class QAOperationCR(IshtarForm): return operation = self.items[0] if not self.profil.parcel_mandatory: - self.fields['town'].choices = [(t.pk, str(t)) - for t in operation.towns.all()] - self.fields['archaeological_site'].choices += [ - (site.pk, str(site)) - for site in operation.archaeological_sites.all() + self.fields["town"].choices = [ + (t.pk, str(t)) for t in operation.towns.all() + ] + self.fields["archaeological_site"].choices += [ + (site.pk, str(site)) for site in operation.archaeological_sites.all() ] if self.profil.parcel_mandatory: - self.fields['parcel'].choices += [('', '--')] + [ - (str(parcel.pk), "{} - {}".format(parcel.short_label, - parcel.town)) - for parcel in operation.parcels.all()] + self.fields["parcel"].choices += [("", "--")] + [ + (str(parcel.pk), "{} - {}".format(parcel.short_label, parcel.town)) + for parcel in operation.parcels.all() + ] def save(self, items): operation = items[0] data = { "operation": operation, - "archaeological_site_id": - self.cleaned_data['archaeological_site'] or None, - "label": self.cleaned_data['label'], - "unit_id": self.cleaned_data['unit'] or None + "archaeological_site_id": self.cleaned_data["archaeological_site"] or None, + "label": self.cleaned_data["label"], + "unit_id": self.cleaned_data["unit"] or None, } if self.profil.parcel_mandatory: - data["parcel_id"] = self.cleaned_data['parcel'] + data["parcel_id"] = self.cleaned_data["parcel"] else: - data["town_id"] = self.cleaned_data['town'] + data["town_id"] = self.cleaned_data["town"] models.ContextRecord.objects.create(**data) @@ -544,29 +626,30 @@ class QAContextRecordDuplicateForm(IshtarForm): qa_label = forms.CharField(label=_("ID"), max_length=None, required=True) qa_parcel = forms.ChoiceField(label=_("Parcel"), choices=[]) qa_town = forms.ChoiceField(label=_("Town"), choices=[], required=False) - qa_unit = forms.ChoiceField(label=_("Context record type"), required=False, - choices=[]) + qa_unit = forms.ChoiceField( + label=_("Context record type"), required=False, choices=[] + ) TYPES = [ - FieldType('qa_unit', models.Unit), + FieldType("qa_unit", models.Unit), ] def __init__(self, *args, **kwargs): self.user = None - if 'user' in kwargs: - self.user = kwargs.pop('user') - if hasattr(self.user, 'ishtaruser'): + if "user" in kwargs: + self.user = kwargs.pop("user") + if hasattr(self.user, "ishtaruser"): self.user = self.user.ishtaruser - self.context_record = kwargs.pop('items')[0] + self.context_record = kwargs.pop("items")[0] super(QAContextRecordDuplicateForm, self).__init__(*args, **kwargs) profile = IshtarSiteProfile.get_current_profile() - self.fields['qa_parcel'].choices = [('', '--')] + self.fields["qa_parcel"].choices = [("", "--")] if not profile.parcel_mandatory: - self.fields['qa_parcel'].required = False - self.fields['qa_town'].choices = [('', '--')] + self.fields["qa_parcel"].required = False + self.fields["qa_town"].choices = [("", "--")] else: - self.fields.pop('qa_town') + self.fields.pop("qa_town") get_init_parcel(self, self.context_record.operation, prefix="qa_") @@ -575,8 +658,9 @@ class QAContextRecordDuplicateForm(IshtarForm): if "qa_parcel" in self.fields and self.context_record.parcel: self.fields["qa_parcel"].initial = self.context_record.parcel.pk - self.fields['qa_label'].initial = ( - self.context_record.label or "") + str(_(" - duplicate")) + self.fields["qa_label"].initial = (self.context_record.label or "") + str( + _(" - duplicate") + ) if self.context_record.unit: self.fields["qa_unit"].initial = self.context_record.unit.pk @@ -584,21 +668,21 @@ class QAContextRecordDuplicateForm(IshtarForm): data = {"label": self.cleaned_data["qa_label"]} if self.cleaned_data.get("qa_unit", None): try: - data["unit"] = models.Unit.objects.get(pk=int( - self.cleaned_data["qa_unit"]), available=True) + data["unit"] = models.Unit.objects.get( + pk=int(self.cleaned_data["qa_unit"]), available=True + ) except models.Unit.DoesNotExist: pass if self.cleaned_data.get("qa_town", None): try: - data["town"] = Town.objects.get(pk=int( - self.cleaned_data["qa_town"])) + data["town"] = Town.objects.get(pk=int(self.cleaned_data["qa_town"])) except Town.DoesNotExist: pass if self.cleaned_data.get("qa_parcel", None): try: - data["parcel"] = Parcel.objects.get(pk=int( - self.cleaned_data["qa_parcel"])) + data["parcel"] = Parcel.objects.get( + pk=int(self.cleaned_data["qa_parcel"]) + ) except Parcel.DoesNotExist: pass - return self.context_record.duplicate( - self.user, data=data) + return self.context_record.duplicate(self.user, data=data) diff --git a/archaeological_context_records/ishtar_menu.py b/archaeological_context_records/ishtar_menu.py index a7efd8da4..6d4ae1a57 100644 --- a/archaeological_context_records/ishtar_menu.py +++ b/archaeological_context_records/ishtar_menu.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -26,25 +26,45 @@ from . import models # be carreful: each access_controls must be relevant with check_rights in urls MENU_SECTIONS = [ - (40, SectionItem('record_management', _("Context record"), - profile_restriction='context_record', - css='menu-context-record', - childs=[MenuItem('record_search', _("Search"), - model=models.ContextRecord, - access_controls=['view_contextrecord', - 'view_own_contextrecord']), - MenuItem('record_creation', _("Creation"), - model=models.ContextRecord, - access_controls=['add_contextrecord', - 'add_own_contextrecord']), - MenuItem('record_modification', _("Modification"), - model=models.ContextRecord, - access_controls=['change_contextrecord', - 'change_own_contextrecord']), - MenuItem('record_deletion', _("Deletion"), - model=models.ContextRecord, - access_controls=['delete_contextrecord', - 'delete_own_contextrecord']), - ]) - ) + ( + 40, + SectionItem( + "record_management", + _("Context record"), + profile_restriction="context_record", + css="menu-context-record", + childs=[ + MenuItem( + "record_search", + _("Search"), + model=models.ContextRecord, + access_controls=["view_contextrecord", "view_own_contextrecord"], + ), + MenuItem( + "record_creation", + _("Creation"), + model=models.ContextRecord, + access_controls=["add_contextrecord", "add_own_contextrecord"], + ), + MenuItem( + "record_modification", + _("Modification"), + model=models.ContextRecord, + access_controls=[ + "change_contextrecord", + "change_own_contextrecord", + ], + ), + MenuItem( + "record_deletion", + _("Deletion"), + model=models.ContextRecord, + access_controls=[ + "delete_contextrecord", + "delete_own_contextrecord", + ], + ), + ], + ), + ) ] diff --git a/archaeological_context_records/lookups.py b/archaeological_context_records/lookups.py index 7b7d5b85d..3131127d8 100644 --- a/archaeological_context_records/lookups.py +++ b/archaeological_context_records/lookups.py @@ -7,19 +7,16 @@ from django.db.models import Q from archaeological_context_records import models -@register('context_record') +@register("context_record") class ContextRecordLookup(LookupChannel): model = models.ContextRecord def get_query(self, q, request): query = Q() - for term in q.strip().split(' '): - subquery = ( - Q(cached_label__icontains=term) | - Q(town__name__icontains=term) - ) + for term in q.strip().split(" "): + subquery = Q(cached_label__icontains=term) | Q(town__name__icontains=term) query &= subquery - return self.model.objects.filter(query).order_by('cached_label')[:20] + return self.model.objects.filter(query).order_by("cached_label")[:20] def format_item_display(self, item): return "<span class='ajax-label'>%s</span>" % item.cached_label diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index 2c43ad810..02d488c85 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2012-2017 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -28,23 +28,47 @@ from django.core.urlresolvers import reverse from django.db import connection from django.db.models import Q from django.db.models.signals import post_delete, post_save, m2m_changed -from ishtar_common.utils import ugettext_lazy as _,\ - pgettext_lazy, pgettext +from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy, pgettext from django.utils.text import slugify -from ishtar_common.utils import cached_label_changed, \ - m2m_historization_changed, post_save_geo - -from ishtar_common.models import Document, GeneralType, \ - BaseHistorizedItem, OwnPerms, ShortMenuItem, \ - GeneralRelationType, GeneralRecordRelations, post_delete_record_relation,\ - post_save_cache, ValueGetter, BulkUpdatedItem, \ - RelationItem, Town, get_current_profile, document_attached_changed, \ - HistoryModel, SearchAltName, GeoItem, CompleteIdentifierItem, SearchVectorConfig, \ - DocumentItem, MainItem, QuickAction +from ishtar_common.utils import ( + cached_label_changed, + m2m_historization_changed, + post_save_geo, +) + +from ishtar_common.models import ( + Document, + GeneralType, + BaseHistorizedItem, + OwnPerms, + ShortMenuItem, + GeneralRelationType, + GeneralRecordRelations, + post_delete_record_relation, + post_save_cache, + ValueGetter, + BulkUpdatedItem, + RelationItem, + Town, + get_current_profile, + document_attached_changed, + HistoryModel, + SearchAltName, + GeoItem, + CompleteIdentifierItem, + SearchVectorConfig, + DocumentItem, + MainItem, + QuickAction, +) from ishtar_common.models_common import HistoricalRecords -from archaeological_operations.models import Operation, Period, Parcel, \ - ArchaeologicalSite +from archaeological_operations.models import ( + Operation, + Period, + Parcel, + ArchaeologicalSite, +) from ishtar_common.model_managers import UUIDModelManager @@ -52,7 +76,7 @@ class DatingType(GeneralType): class Meta: verbose_name = _("Dating type") verbose_name_plural = _("Dating types") - ordering = ('label',) + ordering = ("label",) post_save.connect(post_save_cache, sender=DatingType) @@ -63,7 +87,7 @@ class DatingQuality(GeneralType): class Meta: verbose_name = _("Dating quality type") verbose_name_plural = _("Dating quality types") - ordering = ('label',) + ordering = ("label",) post_save.connect(post_save_cache, sender=DatingQuality) @@ -75,48 +99,55 @@ class Dating(models.Model): period = models.ForeignKey(Period, verbose_name=_("Period")) start_date = models.IntegerField(_("Start date"), blank=True, null=True) end_date = models.IntegerField(_("End date"), blank=True, null=True) - dating_type = models.ForeignKey(DatingType, verbose_name=_("Dating type"), - on_delete=models.SET_NULL, - blank=True, null=True) - quality = models.ForeignKey(DatingQuality, verbose_name=_("Quality"), - on_delete=models.SET_NULL, - blank=True, null=True) - precise_dating = models.TextField( - _("Precise dating"), blank=True, default="") + dating_type = models.ForeignKey( + DatingType, + verbose_name=_("Dating type"), + on_delete=models.SET_NULL, + blank=True, + null=True, + ) + quality = models.ForeignKey( + DatingQuality, + verbose_name=_("Quality"), + on_delete=models.SET_NULL, + blank=True, + null=True, + ) + precise_dating = models.TextField(_("Precise dating"), blank=True, default="") objects = UUIDModelManager() ASSOCIATED_ALT_NAMES = { - 'datings__period': SearchAltName( + "datings__period": SearchAltName( pgettext_lazy("key for text search", "datings-period"), - 'datings__period__label__iexact' + "datings__period__label__iexact", ), "datings__precise_dating": SearchAltName( pgettext_lazy("key for text search", "datings-precise"), - 'datings__precise_dating__iexact' + "datings__precise_dating__iexact", ), "datings__start_date__before": SearchAltName( pgettext_lazy("key for text search", "datings-start-before"), - 'datings__start_date__lte' + "datings__start_date__lte", ), "datings__start_date__after": SearchAltName( pgettext_lazy("key for text search", "datings-start-after"), - 'datings__start_date__gte' + "datings__start_date__gte", ), "datings__end_date__before": SearchAltName( pgettext_lazy("key for text search", "datings-end-before"), - 'datings__end_date__lte' + "datings__end_date__lte", ), "datings__end_date__after": SearchAltName( pgettext_lazy("key for text search", "datings-end-after"), - 'datings__end_date__gte' + "datings__end_date__gte", ), "datings__dating_type": SearchAltName( pgettext_lazy("key for text search", "datings-type"), - 'datings__dating_type__label__iexact' + "datings__dating_type__label__iexact", ), "datings__quality": SearchAltName( pgettext_lazy("key for text search", "datings-quality"), - 'datings__quality__label__iexact' - ) + "datings__quality__label__iexact", + ), } class Meta: @@ -133,39 +164,45 @@ class Dating(models.Model): return "%s (%s-%s)" % (self.period, start_date, end_date) def natural_key(self): - return self.uuid, + return (self.uuid,) - def get_values(self, prefix='', no_values=False, filtr=None, **kwargs): + def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): values = {} if not filtr or prefix + "period" in filtr: values[prefix + "period"] = str(self.period) if not filtr or prefix + "start_date" in filtr: - values[prefix + "start_date"] = self.start_date or '' + values[prefix + "start_date"] = self.start_date or "" if not filtr or prefix + "end_date" in filtr: - values[prefix + "end_date"] = self.end_date or '' + values[prefix + "end_date"] = self.end_date or "" if not filtr or prefix + "dating_type" in filtr: - values[prefix + "dating_type"] = \ + values[prefix + "dating_type"] = ( str(self.dating_type) if self.dating_type else "" + ) if not filtr or prefix + "quality" in filtr: - values[prefix + "quality"] = \ - str(self.quality) if self.quality else "" + values[prefix + "quality"] = str(self.quality) if self.quality else "" if not filtr or prefix + "precise_dating" in filtr: values[prefix + "precise_dating"] = self.precise_dating return values - HISTORY_ATTR = ["period", "start_date", "end_date", "dating_type", - "quality", "precise_dating"] + HISTORY_ATTR = [ + "period", + "start_date", + "end_date", + "dating_type", + "quality", + "precise_dating", + ] def history_compress(self): values = {} for attr in self.HISTORY_ATTR: val = getattr(self, attr) - if hasattr(val, 'history_compress'): + if hasattr(val, "history_compress"): val = val.history_compress() - elif hasattr(val, 'isoformat'): + elif hasattr(val, "isoformat"): val = val.isoformat() elif val is None: - val = '' + val = "" else: val = str(val) values[attr] = val @@ -180,7 +217,7 @@ class Dating(models.Model): res = {} for key in value: val = value[key] - if val == '' and key != "precise_dating": + if val == "" and key != "precise_dating": val = None elif key in ("period", "dating_type", "quality"): field = cls._meta.get_field(key) @@ -203,8 +240,14 @@ class Dating(models.Model): Compare two dating attribute by attribute and return True if all attribute is identical """ - for attr in ["period", "start_date", "end_date", "dating_type", - "quality", "precise_dating"]: + for attr in [ + "period", + "start_date", + "end_date", + "dating_type", + "quality", + "precise_dating", + ]: value1 = getattr(dating_1, attr) value2 = getattr(dating_2, attr) if attr == "precise_dating": @@ -218,11 +261,13 @@ class Dating(models.Model): def context_records_lbl(self): return " - ".join(cr.cached_label for cr in self.context_records.all()) + context_records_lbl.short_description = _("Context record") context_records_lbl.admin_order_field = "context_records__cached_label" def finds_lbl(self): return " - ".join(f.cached_label for f in self.find.all()) + finds_lbl.short_description = _("Find") finds_lbl.admin_order_field = "find__cached_label" @@ -232,9 +277,15 @@ class Dating(models.Model): Fix redundant m2m dating association (usually after imports) """ current_datings = [] - for dating in obj.datings.order_by('pk').all(): - key = (dating.period.pk, dating.start_date, dating.end_date, - dating.dating_type, dating.quality, dating.precise_dating) + for dating in obj.datings.order_by("pk").all(): + key = ( + dating.period.pk, + dating.start_date, + dating.end_date, + dating.dating_type, + dating.quality, + dating.precise_dating, + ) if key not in current_datings: current_datings.append(key) continue @@ -244,13 +295,17 @@ class Dating(models.Model): class Unit(GeneralType): order = models.IntegerField(_("Order")) parent = models.ForeignKey( - "Unit", verbose_name=_("Parent context record type"), - on_delete=models.SET_NULL, blank=True, null=True) + "Unit", + verbose_name=_("Parent context record type"), + on_delete=models.SET_NULL, + blank=True, + null=True, + ) class Meta: verbose_name = _("Context record Type") verbose_name_plural = _("Context record Types") - ordering = ('order', 'label') + ordering = ("order", "label") def __str__(self): return self.label @@ -266,7 +321,7 @@ class ActivityType(GeneralType): class Meta: verbose_name = _("Activity Type") verbose_name_plural = _("Activity Types") - ordering = ('order',) + ordering = ("order",) def __str__(self): return self.label @@ -282,7 +337,7 @@ class IdentificationType(GeneralType): class Meta: verbose_name = _("Identification Type") verbose_name_plural = _("Identification Types") - ordering = ('order', 'label') + ordering = ("order", "label") def __str__(self): return self.label @@ -296,7 +351,7 @@ class ExcavationTechnicType(GeneralType): class Meta: verbose_name = _("Excavation technique type") verbose_name_plural = _("Excavation technique types") - ordering = ('label',) + ordering = ("label",) post_save.connect(post_save_cache, sender=ExcavationTechnicType) @@ -307,7 +362,7 @@ class DocumentationType(GeneralType): class Meta: verbose_name = _("Documentation type") verbose_name_plural = _("Documentation types") - ordering = ('label',) + ordering = ("label",) post_save.connect(post_save_cache, sender=DocumentationType) @@ -334,138 +389,152 @@ class CRBulkView(object): """ -class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, - CompleteIdentifierItem, GeoItem, OwnPerms, ValueGetter, MainItem, - RelationItem): - SLUG = 'contextrecord' +class ContextRecord( + BulkUpdatedItem, + DocumentItem, + BaseHistorizedItem, + CompleteIdentifierItem, + GeoItem, + OwnPerms, + ValueGetter, + MainItem, + RelationItem, +): + SLUG = "contextrecord" APP = "archaeological-context-records" MODEL = "context-record" - SHOW_URL = 'show-contextrecord' - DELETE_URL = 'delete-contextrecord' - EXTERNAL_ID_KEY = 'context_record_external_id' - EXTERNAL_ID_DEPENDENCIES = ['base_finds'] - TABLE_COLS = ['label', 'operation__common_name', 'town__name', - 'parcel__cached_label', 'unit__label'] - if settings.COUNTRY == 'fr': - TABLE_COLS.insert(1, 'operation__code_patriarche') - TABLE_COLS_FOR_OPE = ['label', 'parcel__cached_label', 'unit__label', - 'cached_periods', 'description'] + SHOW_URL = "show-contextrecord" + DELETE_URL = "delete-contextrecord" + EXTERNAL_ID_KEY = "context_record_external_id" + EXTERNAL_ID_DEPENDENCIES = ["base_finds"] + TABLE_COLS = [ + "label", + "operation__common_name", + "town__name", + "parcel__cached_label", + "unit__label", + ] + if settings.COUNTRY == "fr": + TABLE_COLS.insert(1, "operation__code_patriarche") + TABLE_COLS_FOR_OPE = [ + "label", + "parcel__cached_label", + "unit__label", + "cached_periods", + "description", + ] NEW_QUERY_ENGINE = True COL_LABELS = { - 'cached_periods': _("Periods"), - 'datings__period__label': _("Periods"), - 'datings__period': _("Datings (period)"), - 'detailed_related_context_records': _("Related context records"), + "cached_periods": _("Periods"), + "datings__period__label": _("Periods"), + "datings__period": _("Datings (period)"), + "detailed_related_context_records": _("Related context records"), "cached_related_context_records": _("Related context records"), - 'operation__code_patriarche': _("Operation (Patriarche code)"), - 'operation__common_name': _("Operation (name)"), - 'parcel__external_id': _("Parcel (external ID)"), - 'town__name': _("Town"), - 'town': _("Town"), - 'parcel__year': _("Parcel (year)"), - 'section__parcel_number': _("Parcel"), - 'parcel__cached_label': _("Parcel"), - 'unit__label': _("Context record type"), + "operation__code_patriarche": _("Operation (Patriarche code)"), + "operation__common_name": _("Operation (name)"), + "parcel__external_id": _("Parcel (external ID)"), + "town__name": _("Town"), + "town": _("Town"), + "parcel__year": _("Parcel (year)"), + "section__parcel_number": _("Parcel"), + "parcel__cached_label": _("Parcel"), + "unit__label": _("Context record type"), } CONTEXTUAL_TABLE_COLS = { - 'full': { - 'related_context_records': 'cached_related_context_records' - } + "full": {"related_context_records": "cached_related_context_records"} } # statistics - STATISTIC_MODALITIES_OPTIONS = OrderedDict([ - ("unit__label", _("Context record type")), - ("datings__period__label", _("Period")), - ("identification__label", _("Identification")), - ("activity__label", _("Activity")), - ("excavation_technic__label", _("Excavation technique")), - ("documents__source_type__label", _("Associated document type")), - ]) - STATISTIC_MODALITIES = [ - key for key, lbl in STATISTIC_MODALITIES_OPTIONS.items()] + STATISTIC_MODALITIES_OPTIONS = OrderedDict( + [ + ("unit__label", _("Context record type")), + ("datings__period__label", _("Period")), + ("identification__label", _("Identification")), + ("activity__label", _("Activity")), + ("excavation_technic__label", _("Excavation technique")), + ("documents__source_type__label", _("Associated document type")), + ] + ) + STATISTIC_MODALITIES = [key for key, lbl in STATISTIC_MODALITIES_OPTIONS.items()] # search parameters EXTRA_REQUEST_KEYS = { - 'town': 'town__pk', - 'town__name': 'town__name', - 'parcel__cached_label': 'parcel__cached_label', - 'operation__year': 'operation__year__contains', - 'year': 'operation__year__contains', - 'operation__code_patriarche': 'operation__code_patriarche', - 'operation__operation_code': 'operation__operation_code', - 'operation__common_name': 'operation__common_name', - 'datings__period': 'datings__period__pk', - 'parcel_0': 'operation__parcels__section', - 'parcel_1': 'operation__parcels__parcel_number', - 'parcel_2': 'operation__parcels__public_domain', - 'label': 'label__icontains', - 'archaeological_sites': 'operation__archaeological_sites__pk', - 'cached_label': 'cached_label__icontains', - 'datings__period__label': 'datings__period__label', - 'operation_id': 'operation_id', - 'unit__label': "unit__label", + "town": "town__pk", + "town__name": "town__name", + "parcel__cached_label": "parcel__cached_label", + "operation__year": "operation__year__contains", + "year": "operation__year__contains", + "operation__code_patriarche": "operation__code_patriarche", + "operation__operation_code": "operation__operation_code", + "operation__common_name": "operation__common_name", + "datings__period": "datings__period__pk", + "parcel_0": "operation__parcels__section", + "parcel_1": "operation__parcels__parcel_number", + "parcel_2": "operation__parcels__public_domain", + "label": "label__icontains", + "archaeological_sites": "operation__archaeological_sites__pk", + "cached_label": "cached_label__icontains", + "datings__period__label": "datings__period__label", + "operation_id": "operation_id", + "unit__label": "unit__label", } - MANY_COUNTED_FIELDS = ['base_finds'] + MANY_COUNTED_FIELDS = ["base_finds"] REVERSED_BOOL_FIELDS = [ - 'documents__image__isnull', - 'documents__associated_file__isnull', - 'documents__associated_url__isnull', + "documents__image__isnull", + "documents__associated_file__isnull", + "documents__associated_url__isnull", ] - RELATION_TYPES_PREFIX = {'ope_relation_types': 'operation__', - 'cr_relation_types': ''} + RELATION_TYPES_PREFIX = { + "ope_relation_types": "operation__", + "cr_relation_types": "", + } # alternative names of fields for searches ALT_NAMES = { - 'label': SearchAltName( - pgettext_lazy("key for text search", "id"), - 'label__iexact' + "label": SearchAltName( + pgettext_lazy("key for text search", "id"), "label__iexact" ), - 'town': SearchAltName( - pgettext_lazy("key for text search", "town"), - 'town__cached_label__iexact' + "town": SearchAltName( + pgettext_lazy("key for text search", "town"), "town__cached_label__iexact" ), - 'operation__year': SearchAltName( - pgettext_lazy("key for text search", "operation-year"), - 'operation__year' + "operation__year": SearchAltName( + pgettext_lazy("key for text search", "operation-year"), "operation__year" ), - 'operation__code_patriarche': SearchAltName( + "operation__code_patriarche": SearchAltName( pgettext_lazy("key for text search", "patriarche"), - 'operation__code_patriarche__iexact' + "operation__code_patriarche__iexact", ), - 'operation__operation_code': SearchAltName( + "operation__operation_code": SearchAltName( pgettext_lazy("key for text search", "operation-code"), - 'operation__operation_code' + "operation__operation_code", ), - 'operation__cached_label': SearchAltName( + "operation__cached_label": SearchAltName( pgettext_lazy("key for text search", "operation"), - 'operation__cached_label__icontains' + "operation__cached_label__icontains", ), - 'archaeological_site': SearchAltName( + "archaeological_site": SearchAltName( pgettext_lazy("key for text search", "site"), - 'archaeological_site__cached_label__icontains' + "archaeological_site__cached_label__icontains", ), - 'ope_relation_types': SearchAltName( + "ope_relation_types": SearchAltName( pgettext_lazy("key for text search", "operation-relation-type"), - 'ope_relation_types' + "ope_relation_types", ), - 'datings__period': SearchAltName( + "datings__period": SearchAltName( pgettext_lazy("key for text search", "period"), - 'datings__period__label__iexact' + "datings__period__label__iexact", ), - 'unit': SearchAltName( - pgettext_lazy("key for text search", "unit-type"), - 'unit__label__iexact' + "unit": SearchAltName( + pgettext_lazy("key for text search", "unit-type"), "unit__label__iexact" ), - 'parcel': SearchAltName( + "parcel": SearchAltName( pgettext_lazy("key for text search", "parcel"), - 'parcel__cached_label__iexact' + "parcel__cached_label__iexact", ), - 'has_finds': SearchAltName( - pgettext_lazy("key for text search", "has-finds"), - 'base_finds' + "has_finds": SearchAltName( + pgettext_lazy("key for text search", "has-finds"), "base_finds" ), - 'cr_relation_types': SearchAltName( + "cr_relation_types": SearchAltName( pgettext_lazy("key for text search", "record-relation-type"), - 'cr_relation_types' + "cr_relation_types", ), } ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES) @@ -478,47 +547,47 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, SearchVectorConfig("label"), SearchVectorConfig("location"), SearchVectorConfig("town__name"), - SearchVectorConfig("interpretation", 'local'), - SearchVectorConfig("filling", 'local'), - SearchVectorConfig("datings_comment", 'local'), + SearchVectorConfig("interpretation", "local"), + SearchVectorConfig("filling", "local"), + SearchVectorConfig("datings_comment", "local"), SearchVectorConfig("identification__label"), SearchVectorConfig("activity__label"), - SearchVectorConfig("excavation_technic__label")] - M2M_SEARCH_VECTORS = [ - SearchVectorConfig("datings__period__label", 'local') + SearchVectorConfig("excavation_technic__label"), ] + M2M_SEARCH_VECTORS = [SearchVectorConfig("datings__period__label", "local")] UP_MODEL_QUERY = { "operation": ( pgettext_lazy("key for text search", "operation"), - 'cached_label'), - "site": ( - pgettext_lazy("key for text search", "site"), - 'cached_label'), + "cached_label", + ), + "site": (pgettext_lazy("key for text search", "site"), "cached_label"), } MAIN_UP_MODEL_QUERY = "operation" RELATIVE_SESSION_NAMES = [ - ('operation', 'operation__pk'), - ('site', 'archaeological_site__pk'), - ('file', 'operation__associated_file__pk'), - ] - HISTORICAL_M2M = [ - 'datings', 'documentations' + ("operation", "operation__pk"), + ("site", "archaeological_site__pk"), + ("file", "operation__associated_file__pk"), ] - CACHED_LABELS = ['cached_label', 'cached_periods', - "cached_related_context_records"] + HISTORICAL_M2M = ["datings", "documentations"] + CACHED_LABELS = ["cached_label", "cached_periods", "cached_related_context_records"] DOWN_MODEL_UPDATE = ["base_finds"] QA_LOCK = QuickAction( - url="contextrecord-qa-lock", icon_class="fa fa-lock", - text=_("Lock/Unlock"), target="many", - rights=['change_contextrecord', 'change_own_contextrecord'] + url="contextrecord-qa-lock", + icon_class="fa fa-lock", + text=_("Lock/Unlock"), + target="many", + rights=["change_contextrecord", "change_own_contextrecord"], ) QUICK_ACTIONS = [ QA_LOCK, QuickAction( - url="contextrecord-qa-duplicate", icon_class="fa fa-clone", - text=_("Duplicate"), target="one", - rights=['change_contextrecord', 'change_own_contextrecord']), + url="contextrecord-qa-duplicate", + icon_class="fa fa-clone", + text=_("Duplicate"), + target="one", + rights=["change_contextrecord", "change_own_contextrecord"], + ), ] history = HistoricalRecords(bases=[HistoryModel]) @@ -528,91 +597,150 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, uuid = models.UUIDField(default=uuid.uuid4) external_id = models.TextField(_("External ID"), blank=True, default="") auto_external_id = models.BooleanField( - _("External ID is set automatically"), default=False) + _("External ID is set automatically"), default=False + ) parcel = models.ForeignKey( - Parcel, verbose_name=_("Parcel"), related_name='context_record', - on_delete=models.SET_NULL, blank=True, null=True) + Parcel, + verbose_name=_("Parcel"), + related_name="context_record", + on_delete=models.SET_NULL, + blank=True, + null=True, + ) town = models.ForeignKey( - Town, verbose_name=_("Town"), related_name='context_record', - on_delete=models.SET_NULL, blank=True, null=True) - operation = models.ForeignKey(Operation, verbose_name=_("Operation"), - related_name='context_record') + Town, + verbose_name=_("Town"), + related_name="context_record", + on_delete=models.SET_NULL, + blank=True, + null=True, + ) + operation = models.ForeignKey( + Operation, verbose_name=_("Operation"), related_name="context_record" + ) archaeological_site = models.ForeignKey( - ArchaeologicalSite, verbose_name=_("Archaeological site"), + ArchaeologicalSite, + verbose_name=_("Archaeological site"), on_delete=models.SET_NULL, - blank=True, null=True, related_name='context_records') + blank=True, + null=True, + related_name="context_records", + ) label = models.CharField(_("ID"), max_length=200) description = models.TextField(_("Description"), blank=True, default="") comment = models.TextField(_("General comment"), blank=True, default="") - opening_date = models.DateField(_("Opening date"), - blank=True, null=True) + opening_date = models.DateField(_("Opening date"), blank=True, null=True) closing_date = models.DateField(_("Closing date"), blank=True, null=True) length = models.FloatField(_("Length (m)"), blank=True, null=True) width = models.FloatField(_("Width (m)"), blank=True, null=True) - thickness = models.FloatField(_("Thickness (m)"), blank=True, - null=True) + thickness = models.FloatField(_("Thickness (m)"), blank=True, null=True) diameter = models.FloatField(_("Diameter (m)"), blank=True, null=True) depth = models.FloatField(_("Depth (m)"), blank=True, null=True) depth_of_appearance = models.FloatField( - _("Depth of appearance (m)"), blank=True, null=True) + _("Depth of appearance (m)"), blank=True, null=True + ) surface = models.IntegerField(_("Surface (m2)"), blank=True, null=True) location = models.TextField( - _("Location"), blank=True, default="", - help_text=_("A short description of the location of the context " - "record")) - datings = models.ManyToManyField(Dating, related_name='context_records') + _("Location"), + blank=True, + default="", + help_text=_("A short description of the location of the context " "record"), + ) + datings = models.ManyToManyField(Dating, related_name="context_records") documentations = models.ManyToManyField(DocumentationType, blank=True) - datings_comment = models.TextField( - _("Comment on datings"), blank=True, default="") - unit = models.ForeignKey(Unit, verbose_name=_("Context record type"), - on_delete=models.SET_NULL, - related_name='+', blank=True, null=True) + datings_comment = models.TextField(_("Comment on datings"), blank=True, default="") + unit = models.ForeignKey( + Unit, + verbose_name=_("Context record type"), + on_delete=models.SET_NULL, + related_name="+", + blank=True, + null=True, + ) filling = models.TextField(_("Filling"), blank=True, default="") - interpretation = models.TextField( - _("Interpretation"), blank=True, default="") + interpretation = models.TextField(_("Interpretation"), blank=True, default="") taq = models.IntegerField( - _("TAQ"), blank=True, null=True, - help_text=_("\"Terminus Ante Quem\" the context record can't have " - "been created after this date")) + _("TAQ"), + blank=True, + null=True, + help_text=_( + '"Terminus Ante Quem" the context record can\'t have ' + "been created after this date" + ), + ) taq_estimated = models.IntegerField( - _("Estimated TAQ"), blank=True, null=True, - help_text=_("Estimation of a \"Terminus Ante Quem\"")) + _("Estimated TAQ"), + blank=True, + null=True, + help_text=_('Estimation of a "Terminus Ante Quem"'), + ) tpq = models.IntegerField( - _("TPQ"), blank=True, null=True, - help_text=_("\"Terminus Post Quem\" the context record can't have " - "been created before this date")) + _("TPQ"), + blank=True, + null=True, + help_text=_( + '"Terminus Post Quem" the context record can\'t have ' + "been created before this date" + ), + ) tpq_estimated = models.IntegerField( - _("Estimated TPQ"), blank=True, null=True, - help_text=_("Estimation of a \"Terminus Post Quem\"")) + _("Estimated TPQ"), + blank=True, + null=True, + help_text=_('Estimation of a "Terminus Post Quem"'), + ) identification = models.ForeignKey( - IdentificationType, blank=True, null=True, + IdentificationType, + blank=True, + null=True, on_delete=models.SET_NULL, - verbose_name=_("Identification"),) - activity = models.ForeignKey(ActivityType, blank=True, null=True, - on_delete=models.SET_NULL, - verbose_name=_("Activity"),) + verbose_name=_("Identification"), + ) + activity = models.ForeignKey( + ActivityType, + blank=True, + null=True, + on_delete=models.SET_NULL, + verbose_name=_("Activity"), + ) excavation_technic = models.ForeignKey( - ExcavationTechnicType, blank=True, null=True, + ExcavationTechnicType, + blank=True, + null=True, on_delete=models.SET_NULL, - verbose_name=_("Excavation technique")) + verbose_name=_("Excavation technique"), + ) related_context_records = models.ManyToManyField( - 'ContextRecord', through='RecordRelations', blank=True) + "ContextRecord", through="RecordRelations", blank=True + ) documents = models.ManyToManyField( - Document, related_name='context_records', verbose_name=_("Documents"), - blank=True) + Document, + related_name="context_records", + verbose_name=_("Documents"), + blank=True, + ) main_image = models.ForeignKey( - Document, related_name='main_image_context_records', + Document, + related_name="main_image_context_records", on_delete=models.SET_NULL, - verbose_name=_("Main image"), blank=True, null=True) - cached_label = models.TextField(_("Cached name"), blank=True, default="", - db_index=True) - cached_periods = models.TextField( - _("Cached periods label"), blank=True, default="", - help_text=_("Generated automatically - do not edit") + verbose_name=_("Main image"), + blank=True, + null=True, + ) + cached_label = models.TextField( + _("Cached name"), blank=True, default="", db_index=True + ) + cached_periods = models.TextField( + _("Cached periods label"), + blank=True, + default="", + help_text=_("Generated automatically - do not edit"), ) cached_related_context_records = models.TextField( - _("Cached related context records"), blank=True, default="", - help_text=_("Generated automatically - do not edit") + _("Cached related context records"), + blank=True, + default="", + help_text=_("Generated automatically - do not edit"), ) class Meta: @@ -625,13 +753,13 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, ("change_own_contextrecord", "Can change own Context Record"), ("delete_own_contextrecord", "Can delete own Context Record"), ) - ordering = ('cached_label',) + ordering = ("cached_label",) indexes = [ - GinIndex(fields=['data']), + GinIndex(fields=["data"]), ] def natural_key(self): - return (self.uuid, ) + return (self.uuid,) @property def name(self): @@ -651,36 +779,39 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, def public_representation(self): dct = super(ContextRecord, self).public_representation() - dct.update({ - "operation": self.operation.public_representation(), - "site": self.archaeological_site and - self.archaeological_site.public_representation(), - "parcel": str(self.parcel), - "town": self.town.label_with_areas if self.town else None, - "label": self.label, - "description": self.description, - "comment": self.comment - }) + dct.update( + { + "operation": self.operation.public_representation(), + "site": self.archaeological_site + and self.archaeological_site.public_representation(), + "parcel": str(self.parcel), + "town": self.town.label_with_areas if self.town else None, + "label": self.label, + "description": self.description, + "comment": self.comment, + } + ) return dct DOC_VALUES = [ ("base_finds", _("List of associated base finds")), ] - def get_values(self, prefix='', no_values=False, filtr=None, **kwargs): + def get_values(self, prefix="", no_values=False, filtr=None, **kwargs): no_base_finds = True if "no_base_finds" in kwargs: no_base_finds = kwargs["no_base_finds"] values = super(ContextRecord, self).get_values( - prefix=prefix, no_values=no_values, filtr=filtr, **kwargs) + prefix=prefix, no_values=no_values, filtr=filtr, **kwargs + ) if prefix and no_base_finds: return values - if not filtr or prefix + 'base_finds' in filtr: - values[prefix + 'base_finds'] = [ - bf.get_values( - prefix=prefix, no_values=True, filtr=None, **kwargs) - for bf in self.base_finds.distinct().all()] + if not filtr or prefix + "base_finds" in filtr: + values[prefix + "base_finds"] = [ + bf.get_values(prefix=prefix, no_values=True, filtr=None, **kwargs) + for bf in self.base_finds.distinct().all() + ] return values def get_town_centroid(self): @@ -722,24 +853,26 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, return self.operation.get_precise_polygons() @classmethod - def cached_label_bulk_update(cls, operation_id=None, parcel_id=None, - transaction_id=None): + def cached_label_bulk_update( + cls, operation_id=None, parcel_id=None, transaction_id=None + ): transaction_id, is_recursion = cls.bulk_recursion( - transaction_id, [operation_id, parcel_id]) + transaction_id, [operation_id, parcel_id] + ) if is_recursion: return if operation_id: where = "operation_id = %s" args = [int(operation_id)] - kwargs = {'operation_id': operation_id} + kwargs = {"operation_id": operation_id} elif parcel_id: where = "parcel_id = %s" args = [int(parcel_id)] - kwargs = {'parcel_id': parcel_id} + kwargs = {"parcel_id": parcel_id} else: return - kwargs['transaction_id'] = transaction_id + kwargs["transaction_id"] = transaction_id profile = get_current_profile() @@ -776,18 +909,27 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, SELECT id FROM archaeological_context_records_contextrecord WHERE {where} ); - """.format(main_ope_prefix=profile.operation_prefix, - ope_prefix=profile.default_operation_prefix, - join=settings.JOINT, where=where) + """.format( + main_ope_prefix=profile.operation_prefix, + ope_prefix=profile.default_operation_prefix, + join=settings.JOINT, + where=where, + ) with connection.cursor() as c: c.execute(sql, args) - cls._meta.get_field( - 'base_finds').related_model.cached_label_bulk_update(**kwargs) + cls._meta.get_field("base_finds").related_model.cached_label_bulk_update( + **kwargs + ) @property def short_label(self): - return settings.JOINT.join([str(item) for item in [ - self.operation.get_reference(), self.parcel, self.label] if item]) + return settings.JOINT.join( + [ + str(item) + for item in [self.operation.get_reference(), self.parcel, self.label] + if item + ] + ) @property def relation_label(self): @@ -796,49 +938,66 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, def all_base_finds(self): BaseFind = apps.get_model("archaeological_finds", "BaseFind") ids = [self.id] + [ - cr.cr_id for cr in ContextRecordTree.objects.filter( - cr_parent_id=self.id)] + cr.cr_id for cr in ContextRecordTree.objects.filter(cr_parent_id=self.id) + ] return BaseFind.objects.filter(context_record_id__in=ids) @property def show_url(self): - return reverse('show-contextrecord', args=[self.pk, '']) + return reverse("show-contextrecord", args=[self.pk, ""]) def get_extra_actions(self, request): # url, base_text, icon, extra_text, extra css class, is a quick action actions = super(ContextRecord, self).get_extra_actions(request) - #is_locked = hasattr(self, "is_locked") and self.is_locked(request.user) - can_edit_cr = self.can_do(request, 'change_contextrecord') + # is_locked = hasattr(self, "is_locked") and self.is_locked(request.user) + can_edit_cr = self.can_do(request, "change_contextrecord") if can_edit_cr: actions += [ - (reverse("contextrecord-qa-duplicate", args=[self.pk]), - _("Duplicate"), "fa fa-clone", "", "", True), + ( + reverse("contextrecord-qa-duplicate", args=[self.pk]), + _("Duplicate"), + "fa fa-clone", + "", + "", + True, + ), ] return actions @classmethod def get_query_owns(cls, ishtaruser): - return cls._construct_query_own( - 'operation__', Operation._get_query_owns_dicts(ishtaruser) - ) | cls._construct_query_own( - 'base_finds__find__basket__', - [{"shared_with": ishtaruser, "shared_write_with": ishtaruser}] - ) | cls._construct_query_own('', [ - {'history_creator': ishtaruser.user_ptr}, - {'operation__end_date__isnull': True} - ]) + return ( + cls._construct_query_own( + "operation__", Operation._get_query_owns_dicts(ishtaruser) + ) + | cls._construct_query_own( + "base_finds__find__basket__", + [{"shared_with": ishtaruser, "shared_write_with": ishtaruser}], + ) + | cls._construct_query_own( + "", + [ + {"history_creator": ishtaruser.user_ptr}, + {"operation__end_date__isnull": True}, + ], + ) + ) @classmethod - def get_owns(cls, user, menu_filtr=None, limit=None, - values=None, get_short_menu_class=None): + def get_owns( + cls, user, menu_filtr=None, limit=None, values=None, get_short_menu_class=None + ): replace_query = None - if menu_filtr and 'operation' in menu_filtr: - replace_query = Q(operation=menu_filtr['operation']) + if menu_filtr and "operation" in menu_filtr: + replace_query = Q(operation=menu_filtr["operation"]) owns = super(ContextRecord, cls).get_owns( - user, replace_query=replace_query, - limit=limit, values=values, - get_short_menu_class=get_short_menu_class) + user, + replace_query=replace_query, + limit=limit, + values=values, + get_short_menu_class=get_short_menu_class, + ) return cls._return_get_owns(owns, values, get_short_menu_class) def full_label(self): @@ -847,15 +1006,22 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, def _real_label(self): if not self.operation.code_patriarche: return - return settings.JOINT.join((self.operation.code_patriarche, - self.label)) + return settings.JOINT.join((self.operation.code_patriarche, self.label)) def _temp_label(self): if self.operation.code_patriarche: return - return settings.JOINT.join([str(lbl) for lbl in [ - self.operation.year, self.operation.operation_code, self.label] - if lbl]) + return settings.JOINT.join( + [ + str(lbl) + for lbl in [ + self.operation.year, + self.operation.operation_code, + self.label, + ] + if lbl + ] + ) def _generate_cached_label(self): return self.full_label() @@ -869,17 +1035,18 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, def _get_associated_cached_labels(self): BaseFind = apps.get_model("archaeological_finds", "BaseFind") Find = apps.get_model("archaeological_finds", "Find") - return list(Find.objects.filter(base_finds__context_record=self).all())\ - + list(BaseFind.objects.filter(context_record=self).all()) + return list(Find.objects.filter(base_finds__context_record=self).all()) + list( + BaseFind.objects.filter(context_record=self).all() + ) def _cached_labels_bulk_update(self): - self.base_finds.model.cached_label_bulk_update( - context_record_id=self.pk) + self.base_finds.model.cached_label_bulk_update(context_record_id=self.pk) return True def _get_base_image_path(self): - return self.operation._get_base_image_path() + \ - "/{}/{}".format(self.SLUG, slugify(self.label or "00")) + return self.operation._get_base_image_path() + "/{}/{}".format( + self.SLUG, slugify(self.label or "00") + ) @property def archaeological_site_reference(self): @@ -887,7 +1054,8 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, return self.archaeological_site.reference if self.operation.archaeological_sites.count(): return "-".join( - a.reference for a in self.operation.archaeological_sites.all()) + a.reference for a in self.operation.archaeological_sites.all() + ) return "" @property @@ -907,15 +1075,15 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, return self.operation.get_town_label() @classmethod - def get_periods(cls, slice='year', fltr={}): + def get_periods(cls, slice="year", fltr={}): q = cls.objects if fltr: q = q.filter(**fltr) - if slice == 'year': + if slice == "year": years = set() - for res in list(q.values('operation__start_date')): - if res['operation__start_date']: - yr = res['operation__start_date'].year + for res in list(q.values("operation__start_date")): + if res["operation__start_date"]: + yr = res["operation__start_date"].year years.add(yr) return list(years) return [] @@ -929,8 +1097,10 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, @classmethod def get_operations(cls): - return [dct['operation__pk'] - for dct in cls.objects.values('operation__pk').distinct()] + return [ + dct["operation__pk"] + for dct in cls.objects.values("operation__pk").distinct() + ] @classmethod def get_by_operation(cls, operation_id): @@ -963,7 +1133,8 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem, def save(self, *args, **kwargs): super(ContextRecord, self).save(*args, **kwargs) if (not self.town and self.parcel) or ( - self.parcel and self.parcel.town != self.town): + self.parcel and self.parcel.town != self.town + ): self.town = self.parcel.town self.skip_history_when_saving = True self.save() @@ -975,40 +1146,44 @@ def context_record_post_save(sender, **kwargs): post_save.connect(context_record_post_save, sender=ContextRecord) -m2m_changed.connect(document_attached_changed, - sender=ContextRecord.documents.through) +m2m_changed.connect(document_attached_changed, sender=ContextRecord.documents.through) for attr in ContextRecord.HISTORICAL_M2M: - m2m_changed.connect(m2m_historization_changed, - sender=getattr(ContextRecord, attr).through) + m2m_changed.connect( + m2m_historization_changed, sender=getattr(ContextRecord, attr).through + ) class RelationType(GeneralRelationType): class Meta: verbose_name = _("Relation type") verbose_name_plural = _("Relation types") - ordering = ('order', 'label') + ordering = ("order", "label") class RecordRelationsManager(models.Manager): def get_by_natural_key(self, left_record, right_record, relation_type): - return self.get(left_record__uuid=left_record, - right_record__uuid=right_record, - relation_type__txt_idx=relation_type) + return self.get( + left_record__uuid=left_record, + right_record__uuid=right_record, + relation_type__txt_idx=relation_type, + ) class RecordRelations(GeneralRecordRelations, models.Model): - MAIN_ATTR = 'left_record' - left_record = models.ForeignKey(ContextRecord, - related_name='right_relations') - right_record = models.ForeignKey(ContextRecord, - related_name='left_relations') + MAIN_ATTR = "left_record" + left_record = models.ForeignKey(ContextRecord, related_name="right_relations") + right_record = models.ForeignKey(ContextRecord, related_name="left_relations") relation_type = models.ForeignKey(RelationType) objects = RecordRelationsManager() TABLE_COLS = [ - "left_record__label", "left_record__unit", "left_record__parcel", + "left_record__label", + "left_record__unit", + "left_record__parcel", "relation_type", - "right_record__label", "right_record__unit", "right_record__parcel", + "right_record__label", + "right_record__unit", + "right_record__parcel", ] COL_LABELS = { "left_record__label": _("ID (left)"), @@ -1021,13 +1196,11 @@ class RecordRelations(GeneralRecordRelations, models.Model): "right_record__unit": _("Context record type (right)"), "right_record__parcel": _("Parcel (right)"), "right_record__description": _("Description (right)"), - "right_record__datings__period": _("Periods (right)") + "right_record__datings__period": _("Periods (right)"), } # search parameters - EXTRA_REQUEST_KEYS = { - "left_record__operation": "left_record__operation__pk" - } + EXTRA_REQUEST_KEYS = {"left_record__operation": "left_record__operation__pk"} class Meta: verbose_name = _("Record relation") @@ -1037,8 +1210,7 @@ class RecordRelations(GeneralRecordRelations, models.Model): ] def natural_key(self): - return self.left_record.uuid, self.right_record.uuid, \ - self.relation_type.txt_idx + return self.left_record.uuid, self.right_record.uuid, self.relation_type.txt_idx post_delete.connect(post_delete_record_relation, sender=RecordRelations) @@ -1062,34 +1234,40 @@ class RecordRelationView(models.Model): """ TABLE_COLS = [ "relation_type", - "right_record__label", "right_record__unit", + "right_record__label", + "right_record__unit", "right_record__parcel", - "right_record__datings__period", "right_record__description"] + "right_record__datings__period", + "right_record__description", + ] COL_LABELS = { "relation_type": _("Relation type"), "right_record__label": _("ID"), "right_record__unit": _("Context record type"), "right_record__parcel": _("Parcel"), "right_record__description": _("Description"), - "right_record__datings__period": _("Periods") + "right_record__datings__period": _("Periods"), } # search parameters EXTRA_REQUEST_KEYS = { "left_record_id": "left_record_id", - "right_record__unit": "right_record__unit__label" + "right_record__unit": "right_record__unit__label", } - left_record = models.ForeignKey(ContextRecord, related_name='+', - on_delete=models.DO_NOTHING) - right_record = models.ForeignKey(ContextRecord, related_name='+', - on_delete=models.DO_NOTHING) - relation_type = models.ForeignKey(RelationType, related_name='+', - on_delete=models.DO_NOTHING) + left_record = models.ForeignKey( + ContextRecord, related_name="+", on_delete=models.DO_NOTHING + ) + right_record = models.ForeignKey( + ContextRecord, related_name="+", on_delete=models.DO_NOTHING + ) + relation_type = models.ForeignKey( + RelationType, related_name="+", on_delete=models.DO_NOTHING + ) class Meta: managed = False - db_table = 'record_relations' - unique_together = ('id', 'right_record') + db_table = "record_relations" + unique_together = ("id", "right_record") permissions = [ ("view_recordrelation", "Can view all record relations - view"), ] @@ -1099,7 +1277,7 @@ class RecordRelationView(models.Model): return [] def __str__(self): - return "{} \"{}\"".format(self.relation_type, self.right_record) + return '{} "{}"'.format(self.relation_type, self.right_record) class ContextRecordTree(models.Model): @@ -1178,13 +1356,14 @@ class ContextRecordTree(models.Model): cr = models.ForeignKey( "archaeological_context_records.ContextRecord", verbose_name=_("Context record"), - related_name="context_record_tree_parent") + related_name="context_record_tree_parent", + ) cr_parent = models.ForeignKey( "archaeological_context_records.ContextRecord", verbose_name=_("Context record parent"), - related_name="context_record_tree_child") + related_name="context_record_tree_child", + ) class Meta: managed = False - db_table = 'context_records_tree' - + db_table = "context_records_tree" diff --git a/archaeological_context_records/serializers.py b/archaeological_context_records/serializers.py index a41e2bd40..2bccc63f7 100644 --- a/archaeological_context_records/serializers.py +++ b/archaeological_context_records/serializers.py @@ -1,16 +1,14 @@ from django.db.models import Q -from ishtar_common.serializers_utils import generic_get_results, \ - archive_serialization +from ishtar_common.serializers_utils import generic_get_results, archive_serialization from archaeological_context_records import models from archaeological_finds.models import Find -from archaeological_finds.serializers import generate_warehouse_queryset \ - as finds_generate_warehouse_queryset +from archaeological_finds.serializers import ( + generate_warehouse_queryset as finds_generate_warehouse_queryset, +) -CR_MODEL_LIST = [ - models.Dating, models.ContextRecord, models.RecordRelations -] +CR_MODEL_LIST = [models.Dating, models.ContextRecord, models.RecordRelations] # TODO: associated documents @@ -22,14 +20,23 @@ def generate_warehouse_queryset(ids): for container_key in ("container", "container_ref"): for warehouse_key in ("location", "responsible"): - q_c = Q(** - {"{}__{}__{}__id__in".format( - base_query_key, container_key, warehouse_key): ids}) - q_r = Q(** - {"left_record__{}__{}__{}__id__in".format( - base_query_key, container_key, warehouse_key): ids, - "right_record__{}__{}__{}__id__in".format( - base_query_key, container_key, warehouse_key): ids}) + q_c = Q( + **{ + "{}__{}__{}__id__in".format( + base_query_key, container_key, warehouse_key + ): ids + } + ) + q_r = Q( + **{ + "left_record__{}__{}__{}__id__in".format( + base_query_key, container_key, warehouse_key + ): ids, + "right_record__{}__{}__{}__id__in".format( + base_query_key, container_key, warehouse_key + ): ids, + } + ) if not q_cr: q_cr = q_c q_record_relation = q_r @@ -38,82 +45,86 @@ def generate_warehouse_queryset(ids): q_record_relation |= q_r result_queryset = { - models.ContextRecord.__name__: models.ContextRecord.objects.filter( - q_cr), - models.RecordRelations.__name__: - models.RecordRelations.objects.filter(q_r) + models.ContextRecord.__name__: models.ContextRecord.objects.filter(q_cr), + models.RecordRelations.__name__: models.RecordRelations.objects.filter(q_r), } return result_queryset -def cr_serialization(archive=False, return_empty_types=False, - archive_name=None, operation_queryset=None, - site_queryset=None, cr_queryset=None, find_queryset=None, - warehouse_queryset=None, get_queryset=False, no_geo=True, - put_locks=False, lock_user=None): +def cr_serialization( + archive=False, + return_empty_types=False, + archive_name=None, + operation_queryset=None, + site_queryset=None, + cr_queryset=None, + find_queryset=None, + warehouse_queryset=None, + get_queryset=False, + no_geo=True, + put_locks=False, + lock_user=None, +): result_queryset = {} find_ids, cr_ids = None, None if operation_queryset: operation_ids = operation_queryset.values_list("id", flat=True) result_queryset = { - models.ContextRecord.__name__: - models.ContextRecord.objects.filter( - operation_id__in=operation_ids), - models.RecordRelations.__name__: - models.RecordRelations.objects.filter( - left_record__operation_id__in=operation_ids, - right_record__operation_id__in=operation_ids, - ), + models.ContextRecord.__name__: models.ContextRecord.objects.filter( + operation_id__in=operation_ids + ), + models.RecordRelations.__name__: models.RecordRelations.objects.filter( + left_record__operation_id__in=operation_ids, + right_record__operation_id__in=operation_ids, + ), } cr_ids = list( - result_queryset[models.ContextRecord.__name__].values_list( - "id", flat=True)) + result_queryset[models.ContextRecord.__name__].values_list("id", flat=True) + ) find_ids = list( Find.objects.filter( base_finds__context_record__operation_id__in=operation_ids - ).values_list("id", flat=True)) + ).values_list("id", flat=True) + ) elif site_queryset: site_ids = site_queryset.values_list("id", flat=True) result_queryset = { - models.ContextRecord.__name__: - models.ContextRecord.objects.filter( - operation__archaeological_sites__id__in=site_ids), - models.RecordRelations.__name__: - models.RecordRelations.objects.filter( - left_record__operation__archaeological_sites__id__in=site_ids, - right_record__operation__archaeological_sites__id__in=site_ids, - ) + models.ContextRecord.__name__: models.ContextRecord.objects.filter( + operation__archaeological_sites__id__in=site_ids + ), + models.RecordRelations.__name__: models.RecordRelations.objects.filter( + left_record__operation__archaeological_sites__id__in=site_ids, + right_record__operation__archaeological_sites__id__in=site_ids, + ), } f_q = { "base_finds__context_record__operation__archaeological_sites__id__in": site_ids } - find_ids = list( - Find.objects.filter(**f_q).values_list("id", flat=True)) + find_ids = list(Find.objects.filter(**f_q).values_list("id", flat=True)) elif cr_queryset: cr_ids = cr_queryset.values_list("id", flat=True) result_queryset = { models.ContextRecord.__name__: cr_queryset, - models.RecordRelations.__name__: - models.RecordRelations.objects.filter( - left_record_id__in=cr_ids, - right_record_id__in=cr_ids, - ) + models.RecordRelations.__name__: models.RecordRelations.objects.filter( + left_record_id__in=cr_ids, + right_record_id__in=cr_ids, + ), } find_ids = list( - Find.objects.filter( - base_finds__context_record__in=cr_ids).values_list( - "id", flat=True)) + Find.objects.filter(base_finds__context_record__in=cr_ids).values_list( + "id", flat=True + ) + ) elif find_queryset: find_ids = find_queryset.values_list("id", flat=True) result_queryset = { models.ContextRecord.__name__: models.ContextRecord.objects.filter( base_finds__find__id__in=find_ids, ), - models.RecordRelations.__name__: - models.RecordRelations.objects.filter( - left_record__base_finds__find__id__in=find_ids, - right_record__base_finds__find__id__in=find_ids, - ) + models.RecordRelations.__name__: models.RecordRelations.objects.filter( + left_record__base_finds__find__id__in=find_ids, + right_record__base_finds__find__id__in=find_ids, + ), } elif warehouse_queryset: warehouse_ids = warehouse_queryset.values_list("id", flat=True) @@ -123,18 +134,18 @@ def cr_serialization(archive=False, return_empty_types=False, if result_queryset: cr_ids = list( - result_queryset[models.ContextRecord.__name__].values_list( - "id", flat=True)) + result_queryset[models.ContextRecord.__name__].values_list("id", flat=True) + ) result_queryset[models.Dating.__name__] = models.Dating.objects.filter( - Q(context_records__id__in=cr_ids) | - Q(find__id__in=list(find_ids)) + Q(context_records__id__in=cr_ids) | Q(find__id__in=list(find_ids)) ) if get_queryset: return result_queryset - result = generic_get_results(CR_MODEL_LIST, "context_records", - result_queryset=result_queryset, no_geo=no_geo) + result = generic_get_results( + CR_MODEL_LIST, "context_records", result_queryset=result_queryset, no_geo=no_geo + ) if put_locks: for model in CR_MODEL_LIST: if not hasattr(model, "locked"): @@ -145,7 +156,10 @@ def cr_serialization(archive=False, return_empty_types=False, q.update(locked=True, lock_user=lock_user) full_archive = archive_serialization( - result, archive_dir="context_records", archive=archive, - return_empty_types=return_empty_types, archive_name=archive_name, + result, + archive_dir="context_records", + archive=archive, + return_empty_types=return_empty_types, + archive_name=archive_name, ) return full_archive diff --git a/archaeological_context_records/tests.py b/archaeological_context_records/tests.py index fef557cf3..64950bd91 100644 --- a/archaeological_context_records/tests.py +++ b/archaeological_context_records/tests.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2015-2018 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -29,21 +29,38 @@ from django.core.urlresolvers import reverse from django.test.client import Client from django.utils.translation import pgettext_lazy -from ishtar_common.models import IshtarSiteProfile, ImporterModel, \ - UserProfile, ProfileType, Town, Area, get_current_profile - -from archaeological_operations.tests import OperationInitTest, \ - ImportTest +from ishtar_common.models import ( + IshtarSiteProfile, + ImporterModel, + UserProfile, + ProfileType, + Town, + Area, + get_current_profile, +) + +from archaeological_operations.tests import OperationInitTest, ImportTest from archaeological_operations import models as models_ope from archaeological_context_records import models from ishtar_common.utils import generate_relation_graph -from ishtar_common.tests import WizardTest, WizardTestFormData as FormData, \ - create_superuser, create_user, TestCase, AutocompleteTestBase, AcItem, \ - CONTEXT_RECORD_FIXTURES, CONTEXT_RECORD_TOWNS_FIXTURES, \ - OPERATION_TOWNS_FIXTURES, GenericSerializationTest, COMMON_FIXTURES, \ - WAREHOUSE_FIXTURES, SearchText +from ishtar_common.tests import ( + WizardTest, + WizardTestFormData as FormData, + create_superuser, + create_user, + TestCase, + AutocompleteTestBase, + AcItem, + CONTEXT_RECORD_FIXTURES, + CONTEXT_RECORD_TOWNS_FIXTURES, + OPERATION_TOWNS_FIXTURES, + GenericSerializationTest, + COMMON_FIXTURES, + WAREHOUSE_FIXTURES, + SearchText, +) from archaeological_operations.models import Operation from archaeological_operations.serializers import operation_serialization @@ -67,14 +84,15 @@ class ImportContextRecordTest(ImportTest, TestCase): current_nb = models.ContextRecord.objects.count() self.assertEqual(current_nb, old_nb + 4) self.assertEqual( - models.ContextRecord.objects.filter( - unit__txt_idx='not_in_context').count(), 3) + models.ContextRecord.objects.filter(unit__txt_idx="not_in_context").count(), + 3, + ) self.assertEqual( - models.ContextRecord.objects.filter( - unit__txt_idx='negative').count(), 1) + models.ContextRecord.objects.filter(unit__txt_idx="negative").count(), 1 + ) def test_model_limitation(self): - locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8') + locale.setlocale(locale.LC_ALL, "fr_FR.UTF-8") old_nb = models.ContextRecord.objects.count() mcc, form = self.init_context_record_import() mcc.created_models.clear() @@ -94,9 +112,9 @@ class ImportContextRecordTest(ImportTest, TestCase): cr.delete() mcc, form = self.init_context_record_import() mcc.created_models.clear() - mcc.created_models.add(ImporterModel.objects.get( - klass='ishtar_common.models.Organization' - )) + mcc.created_models.add( + ImporterModel.objects.get(klass="ishtar_common.models.Organization") + ) impt = form.save(self.ishtar_user) impt.initialize() self.init_cr_targetkey(impt) @@ -105,8 +123,8 @@ class ImportContextRecordTest(ImportTest, TestCase): impt.importation() self.assertEqual(len(impt.errors), 5) self.assertTrue( - "doesn't exist in the database." in impt.errors[0]['error'] or - "n'existe pas dans la base" in impt.errors[0]['error'] + "doesn't exist in the database." in impt.errors[0]["error"] + or "n'existe pas dans la base" in impt.errors[0]["error"] ) # retry with only Dating (no context record) @@ -115,8 +133,9 @@ class ImportContextRecordTest(ImportTest, TestCase): mcc, form = self.init_context_record_import() mcc.created_models.clear() dat_model, c = ImporterModel.objects.get_or_create( - klass='archaeological_context_records.models.Dating', - defaults={"name": 'Dating'}) + klass="archaeological_context_records.models.Dating", + defaults={"name": "Dating"}, + ) mcc.created_models.add(dat_model) impt = form.save(self.ishtar_user) impt.initialize() @@ -131,9 +150,11 @@ class ImportContextRecordTest(ImportTest, TestCase): cr.delete() mcc, form = self.init_context_record_import() mcc.created_models.clear() - mcc.created_models.add(ImporterModel.objects.get( - klass='archaeological_context_records.models.ContextRecord' - )) + mcc.created_models.add( + ImporterModel.objects.get( + klass="archaeological_context_records.models.ContextRecord" + ) + ) mcc.created_models.add(dat_model) impt = form.save(self.ishtar_user) impt.initialize() @@ -141,7 +162,7 @@ class ImportContextRecordTest(ImportTest, TestCase): impt.importation() current_nb = models.ContextRecord.objects.count() self.assertEqual(current_nb, 4) - ''' + """ # add a context record model for cr in models.ContextRecord.objects.all(): @@ -157,7 +178,7 @@ class ImportContextRecordTest(ImportTest, TestCase): impt.importation() current_nb = models.ContextRecord.objects.count() self.assertEqual(current_nb, 4) - ''' + """ class ContextRecordInit(OperationInitTest): @@ -165,31 +186,31 @@ class ContextRecordInit(OperationInitTest): if not data: data = {} - if not getattr(self, 'context_records', None): + if not getattr(self, "context_records", None): self.context_records = [] - default = {'label': "Context record"} - if force or not data.get('operation') \ - or not models.Operation.objects.filter( - pk=data['operation'].pk).count(): - data['operation'] = self.get_default_operation(force=force, - user=user) - if not data.get('parcel') or not data['parcel'].pk \ - or not models.Parcel.objects.filter( - pk=data['parcel'].pk).count(): - data['parcel'] = self.get_default_parcel(force=force) + default = {"label": "Context record"} + if ( + force + or not data.get("operation") + or not models.Operation.objects.filter(pk=data["operation"].pk).count() + ): + data["operation"] = self.get_default_operation(force=force, user=user) + if ( + not data.get("parcel") + or not data["parcel"].pk + or not models.Parcel.objects.filter(pk=data["parcel"].pk).count() + ): + data["parcel"] = self.get_default_parcel(force=force) if user: - data['history_modifier'] = user - elif not data.get('history_modifier'): - data['history_modifier'] = self.get_default_user() + data["history_modifier"] = user + elif not data.get("history_modifier"): + data["history_modifier"] = self.get_default_user() default.update(data) - data['operation'] = models.Operation.objects.get( - pk=data['operation'].pk) - data['parcel'] = models.Parcel.objects.get( - pk=data['parcel'].pk) - self.context_records.append(models.ContextRecord.objects.create( - **default)) + data["operation"] = models.Operation.objects.get(pk=data["operation"].pk) + data["parcel"] = models.Parcel.objects.get(pk=data["parcel"].pk) + self.context_records.append(models.ContextRecord.objects.create(**default)) return self.context_records def get_default_context_record(self, force=False, user=None): @@ -198,7 +219,7 @@ class ContextRecordInit(OperationInitTest): return self.create_context_record(force=force, user=user)[0] def tearDown(self): - if hasattr(self, 'context_records'): + if hasattr(self, "context_records"): for cr in self.context_records: try: cr.delete() @@ -214,84 +235,80 @@ class SerializationTest(GenericSerializationTest, ContextRecordInit, TestCase): def setUp(self): ope1 = self.create_operation()[0] ope2 = self.create_operation()[1] - cr = self.create_context_record( - data={"label": "CR 1", "operation": ope1} - )[0] - cr2 = self.create_context_record( - data={"label": "CR 2", "operation": ope2} - )[1] + cr = self.create_context_record(data={"label": "CR 1", "operation": ope1})[0] + cr2 = self.create_context_record(data={"label": "CR 2", "operation": ope2})[1] dating = models.Dating.objects.create( period=models.Period.objects.all()[0], ) cr.datings.add(dating) rlt = models.RelationType.objects.create( - label="Test", - txt_idx="test", - symmetrical=False + label="Test", txt_idx="test", symmetrical=False ) models.RecordRelations.objects.create( - left_record=cr, - right_record=cr2, - relation_type=rlt + left_record=cr, right_record=cr2, relation_type=rlt ) def test_serialization(self): res = self.generic_serialization_test(serializers.cr_serialization) cr_json = json.loads( - res[('context_records', - 'archaeological_context_records__ContextRecord')] + res[("context_records", "archaeological_context_records__ContextRecord")] ) self.assertEqual(len(cr_json), 2) result_queryset = Operation.objects.filter(uuid=self.operations[0].uuid) res = self.generic_serialization_test( - serializers.cr_serialization, no_test=True, - kwargs={"operation_queryset": result_queryset} + serializers.cr_serialization, + no_test=True, + kwargs={"operation_queryset": result_queryset}, ) cr_json = json.loads( - res[('context_records', - 'archaeological_context_records__ContextRecord')] + res[("context_records", "archaeological_context_records__ContextRecord")] ) self.assertEqual(len(cr_json), 1) result_queryset = models.ContextRecord.objects.filter( - uuid=self.context_records[0].uuid) + uuid=self.context_records[0].uuid + ) res = self.generic_serialization_test( - serializers.cr_serialization, no_test=True, - kwargs={"cr_queryset": result_queryset} + serializers.cr_serialization, + no_test=True, + kwargs={"cr_queryset": result_queryset}, ) cr_json = json.loads( - res[('context_records', - 'archaeological_context_records__ContextRecord')] + res[("context_records", "archaeological_context_records__ContextRecord")] ) self.assertEqual(len(cr_json), 1) def test_ope_serialization_with_cr_filter(self): res = self.generic_serialization_test( - operation_serialization, no_test=True, + operation_serialization, + no_test=True, ) ope_json = json.loads( - res[('operations', 'archaeological_operations__Operation')] + res[("operations", "archaeological_operations__Operation")] ) self.assertEqual(len(ope_json), 2) result_queryset = models.ContextRecord.objects.filter( - uuid=self.context_records[0].uuid) + uuid=self.context_records[0].uuid + ) res = self.generic_serialization_test( - operation_serialization, no_test=True, - kwargs={"cr_queryset": result_queryset} + operation_serialization, + no_test=True, + kwargs={"cr_queryset": result_queryset}, ) ope_json = json.loads( - res[('operations', 'archaeological_operations__Operation')] + res[("operations", "archaeological_operations__Operation")] ) self.assertEqual(len(ope_json), 1) def test_restore(self): current_number, zip_filename = self.generic_restore_test_genzip( - serializers.CR_MODEL_LIST, - serializers.cr_serialization) - self.generic_restore_test(zip_filename, current_number, - serializers.CR_MODEL_LIST) + serializers.CR_MODEL_LIST, serializers.cr_serialization + ) + self.generic_restore_test( + zip_filename, current_number, serializers.CR_MODEL_LIST + ) class ExportTest(ContextRecordInit, TestCase): @@ -306,22 +323,22 @@ class ExportTest(ContextRecordInit, TestCase): ope.save() cr = self.create_context_record(data={"label": "CR 1"})[0] c = Client() - url = reverse('get-by-importer', - kwargs={'slug': 'ishtar-context-record', - 'type': 'csv'}) + url = reverse( + "get-by-importer", kwargs={"slug": "ishtar-context-record", "type": "csv"} + ) response = c.get(url) # no result when no authentication self.assertTrue(not response.content) c.login(username=self.username, password=self.password) response = c.get(url) - ENCODING = settings.ENCODING or 'utf-8' + ENCODING = settings.ENCODING or "utf-8" rows = list(csv.reader(StringIO(response.content.decode(ENCODING)))) # one header + one context record self.assertEqual(len(rows), 2) row_cr = rows[1] - self.assertEqual(row_cr[0], '45000') - self.assertEqual(row_cr[1], '12345') - self.assertEqual(row_cr[2], 'A1') + self.assertEqual(row_cr[0], "45000") + self.assertEqual(row_cr[1], "12345") + self.assertEqual(row_cr[2], "A1") class ContextRecordTest(ContextRecordInit, TestCase): @@ -335,17 +352,17 @@ class ContextRecordTest(ContextRecordInit, TestCase): cr_1 = self.context_records[0] cr_2 = self.context_records[1] - sym_rel_type = models.RelationType.objects.filter( - symmetrical=True).all()[0] + sym_rel_type = models.RelationType.objects.filter(symmetrical=True).all()[0] self.cr_rel_type = sym_rel_type models.RecordRelations.objects.create( - left_record=cr_1, right_record=cr_2, relation_type=sym_rel_type) + left_record=cr_1, right_record=cr_2, relation_type=sym_rel_type + ) def test_external_id(self): cr = self.context_records[0] self.assertEqual( - cr.external_id, - "{}-{}".format(cr.parcel.external_id, cr.label)) + cr.external_id, "{}-{}".format(cr.parcel.external_id, cr.label) + ) def test_lost_parcel_dont_delete_context_record(self): cr = self.create_context_record(force=True)[0] @@ -353,12 +370,10 @@ class ContextRecordTest(ContextRecordInit, TestCase): parcel.operation = None parcel.save() # associated context record is not removed - self.assertEqual( - models.ContextRecord.objects.filter(pk=cr.pk).count(), 1) + self.assertEqual(models.ContextRecord.objects.filter(pk=cr.pk).count(), 1) # associated operation is restored self.assertEqual( - models.Parcel.objects.get(pk=parcel.pk).operation, - cr.operation + models.Parcel.objects.get(pk=parcel.pk).operation, cr.operation ) def test_search_vector_update(self): @@ -369,7 +384,7 @@ class ContextRecordTest(ContextRecordInit, TestCase): cr.save() cr = models.ContextRecord.objects.get(pk=cr.pk) self.assertIsNotNone(cr.search_vector) - for key in ('label', 'heeer'): + for key in ("label", "heeer"): self.assertIn(key, cr.search_vector) cr.operation.code_patriarche = "PATRIARCHE" cr.operation.save() @@ -377,16 +392,15 @@ class ContextRecordTest(ContextRecordInit, TestCase): profile = get_current_profile() self.assertIsNotNone(cr.cached_label) - self.assertIn(profile.operation_prefix.lower() + "patriarch", - cr.search_vector) + self.assertIn(profile.operation_prefix.lower() + "patriarch", cr.search_vector) def test_upstream_cache_update(self): cr = self.create_context_record()[0] cr_pk = cr.pk self.assertIsNotNone(cr.cached_label) # OA1 | A | 1 | CR 1 - ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(' | ') - self.assertEqual(ope_id, 'OA1') + ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(" | ") + self.assertEqual(ope_id, "OA1") self.assertEqual(parcel_sec, cr.parcel.section) self.assertEqual(parcel_nb, cr.parcel.parcel_number) self.assertEqual(cr_label, cr.label) @@ -396,7 +410,7 @@ class ContextRecordTest(ContextRecordInit, TestCase): cr.save() cr = models.ContextRecord.objects.get(pk=cr_pk) self.assertIsNotNone(cr.cached_label) - ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(' | ') + ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(" | ") self.assertEqual(cr_label, new_lbl) new_sec, new_nb = "B", "42" @@ -406,7 +420,7 @@ class ContextRecordTest(ContextRecordInit, TestCase): parcel.save() cr = models.ContextRecord.objects.get(pk=cr_pk) self.assertIsNotNone(cr.cached_label) - ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(' | ') + ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(" | ") self.assertEqual(parcel_sec, new_sec) self.assertEqual(parcel_nb, new_nb) @@ -414,8 +428,8 @@ class ContextRecordTest(ContextRecordInit, TestCase): cr.operation.save() cr = models.ContextRecord.objects.get(pk=cr_pk) self.assertIsNotNone(cr.cached_label) - ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(' | ') - self.assertEqual(ope_id, 'OA1') + ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(" | ") + self.assertEqual(ope_id, "OA1") def test_downstream_cache_update(self): cr = self.create_context_record()[0] @@ -423,19 +437,19 @@ class ContextRecordTest(ContextRecordInit, TestCase): from archaeological_finds.models import Find, BaseFind, MaterialType data = { - 'label': "Find me a reason", - 'context_record': cr, - 'history_modifier': self.get_default_user() + "label": "Find me a reason", + "context_record": cr, + "history_modifier": self.get_default_user(), } bf = BaseFind.objects.create(**data) find = Find.objects.create( - history_modifier=self.get_default_user(), - label='Find me too' + history_modifier=self.get_default_user(), label="Find me too" ) find.base_finds.add(bf) mat = MaterialType.objects.create( - label='Adamentium', txt_idx='admentium', code='ADA') + label="Adamentium", txt_idx="admentium", code="ADA" + ) find.material_types.add(mat) class TestObj(object): @@ -443,7 +457,7 @@ class ContextRecordTest(ContextRecordInit, TestCase): self.find_reached = [] def reached(self, sender, **kwargs): - instance = kwargs.get('instance') + instance = kwargs.get("instance") if sender in (Find, BaseFind): self.find_reached.append(instance) @@ -464,21 +478,23 @@ class ContextRecordTest(ContextRecordInit, TestCase): def test_show(self): obj = self.context_records[0] c = Client() - response = c.get(reverse('show-contextrecord', kwargs={'pk': obj.pk})) + response = c.get(reverse("show-contextrecord", kwargs={"pk": obj.pk})) self.assertEqual(response.status_code, 200) # empty content when not allowed self.assertEqual(response.content, b"") c.login(username=self.username, password=self.password) - response = c.get(reverse('show-contextrecord', kwargs={'pk': obj.pk})) + response = c.get(reverse("show-contextrecord", kwargs={"pk": obj.pk})) self.assertEqual(response.status_code, 200) self.assertIn(b'class="card sheet"', response.content) def test_redundant_dating_clean(self): obj = self.context_records[0] - values = {'period': models.Period.objects.all()[0]} - values_2 = {'period': models.Period.objects.all()[0], - 'quality': models.DatingQuality.objects.all()[0]} + values = {"period": models.Period.objects.all()[0]} + values_2 = { + "period": models.Period.objects.all()[0], + "quality": models.DatingQuality.objects.all()[0], + } obj.datings.add(models.Dating.objects.create(**values)) obj.datings.add(models.Dating.objects.create(**values)) @@ -490,10 +506,11 @@ class ContextRecordTest(ContextRecordInit, TestCase): def test_custom_index(self): profile, created = IshtarSiteProfile.objects.get_or_create( - slug='default', active=True) + slug="default", active=True + ) # key: operation - profile.contextrecord_custom_index = 'operation_id' + profile.contextrecord_custom_index = "operation_id" profile.save() cr1 = self.context_records[0] cr1 = models.ContextRecord.objects.get(pk=cr1.pk) @@ -507,17 +524,16 @@ class ContextRecordTest(ContextRecordInit, TestCase): cr2 = models.ContextRecord.objects.get(pk=cr2.pk) self.assertEqual(cr2.custom_index, 2) ope = self.create_operation()[-1] - cr3 = self.create_context_record( - data={"operation": ope})[-1] + cr3 = self.create_context_record(data={"operation": ope})[-1] cr3 = models.ContextRecord.objects.get(pk=cr3.pk) self.assertEqual(cr3.custom_index, 1) # key: operation, unit - profile.contextrecord_custom_index = 'unit_id;operation_id' + profile.contextrecord_custom_index = "unit_id;operation_id" profile.save() - su = models.Unit.objects.get(txt_idx='stratigraphic-unit') - dest = models.Unit.objects.get(txt_idx='sector') + su = models.Unit.objects.get(txt_idx="stratigraphic-unit") + dest = models.Unit.objects.get(txt_idx="sector") cr1.unit, cr2.unit = su, dest cr1.save() cr2.save() @@ -547,7 +563,7 @@ class ContextRecordTest(ContextRecordInit, TestCase): class ContextRecordSearchTest(ContextRecordInit, TestCase, SearchText): fixtures = CONTEXT_RECORD_TOWNS_FIXTURES - SEARCH_URL = 'get-contextrecord' + SEARCH_URL = "get-contextrecord" def setUp(self): IshtarSiteProfile.objects.create() @@ -557,29 +573,30 @@ class ContextRecordSearchTest(ContextRecordInit, TestCase, SearchText): cr_1 = self.context_records[0] cr_2 = self.context_records[1] - sym_rel_type = models.RelationType.objects.filter( - symmetrical=True).all()[0] + sym_rel_type = models.RelationType.objects.filter(symmetrical=True).all()[0] self.cr_rel_type = sym_rel_type models.RecordRelations.objects.create( - left_record=cr_1, right_record=cr_2, relation_type=sym_rel_type) + left_record=cr_1, right_record=cr_2, relation_type=sym_rel_type + ) def test_town_search(self): c = Client() c.login(username=self.username, password=self.password) - data = {'numero_insee': '98989', 'name': 'base_town'} + data = {"numero_insee": "98989", "name": "base_town"} base_town = self.create_towns(datas=data)[-1] - parcel = self.create_parcel(data={'town': base_town, - 'section': 'A', 'parcel_number': '1'})[-1] + parcel = self.create_parcel( + data={"town": base_town, "section": "A", "parcel_number": "1"} + )[-1] self.context_records[0].parcel = parcel self.context_records[0].save() - data = {'numero_insee': '56789', 'name': 'parent_town'} + data = {"numero_insee": "56789", "name": "parent_town"} parent_town = self.create_towns(datas=data)[-1] parent_town.children.add(base_town) - data = {'numero_insee': '01234', 'name': 'child_town'} + data = {"numero_insee": "01234", "name": "child_town"} child_town = self.create_towns(datas=data)[-1] base_town.children.add(child_town) @@ -587,57 +604,50 @@ class ContextRecordSearchTest(ContextRecordInit, TestCase, SearchText): # simple search search = {town_key: base_town.cached_label} - response = c.get(reverse('get-contextrecord'), search) + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) - self.assertEqual( - json.loads(response.content.decode())['recordsTotal'], 1) + self.assertEqual(json.loads(response.content.decode())["recordsTotal"], 1) # parent search search = {town_key: parent_town.cached_label} - response = c.get(reverse('get-contextrecord'), search) + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) - self.assertEqual( - json.loads(response.content.decode())['recordsTotal'], 1) + self.assertEqual(json.loads(response.content.decode())["recordsTotal"], 1) # child search search = {town_key: child_town.cached_label} - response = c.get(reverse('get-contextrecord'), search) + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) - self.assertEqual( - json.loads(response.content.decode())['recordsTotal'], 1) + self.assertEqual(json.loads(response.content.decode())["recordsTotal"], 1) def test_search_export(self): c = Client() - response = c.get(reverse('get-contextrecord')) + response = c.get(reverse("get-contextrecord")) # no result when no authentification self.assertTrue(not json.loads(response.content.decode())) c.login(username=self.username, password=self.password) - response = c.get(reverse('get-contextrecord')) - self.assertEqual( - json.loads(response.content.decode())['recordsTotal'], 2) + response = c.get(reverse("get-contextrecord")) + self.assertEqual(json.loads(response.content.decode())["recordsTotal"], 2) # test search label - response = c.get(reverse('get-contextrecord'), {'label': 'cr 1'}) - self.assertEqual( - json.loads(response.content.decode())['recordsTotal'], 1) + response = c.get(reverse("get-contextrecord"), {"label": "cr 1"}) + self.assertEqual(json.loads(response.content.decode())["recordsTotal"], 1) # test search between relations - rel_rec_key = pgettext_lazy("key for text search", - "record-relation-type") + rel_rec_key = pgettext_lazy("key for text search", "record-relation-type") response = c.get( - reverse('get-contextrecord'), - {'search_vector': 'label="cr 1" {}="{}"'.format( - rel_rec_key, self.cr_rel_type.label) - } + reverse("get-contextrecord"), + { + "search_vector": 'label="cr 1" {}="{}"'.format( + rel_rec_key, self.cr_rel_type.label + ) + }, ) - self.assertEqual( - json.loads(response.content.decode())['recordsTotal'], 2) + self.assertEqual(json.loads(response.content.decode())["recordsTotal"], 2) # test search vector - response = c.get(reverse('get-contextrecord'), {'search_vector': 'CR'}) - self.assertEqual(json.loads(response.content.decode())['recordsTotal'], - 2) + response = c.get(reverse("get-contextrecord"), {"search_vector": "CR"}) + self.assertEqual(json.loads(response.content.decode())["recordsTotal"], 2) # the 2 context records have the same operation - response = c.get(reverse('get-contextrecord'), {'search_vector': 'oa1'}) - self.assertEqual(json.loads(response.content.decode())['recordsTotal'], - 2) + response = c.get(reverse("get-contextrecord"), {"search_vector": "oa1"}) + self.assertEqual(json.loads(response.content.decode())["recordsTotal"], 2) # test search between related operations first_ope = self.operations[0] first_ope.year = 2010 @@ -652,72 +662,71 @@ class ContextRecordSearchTest(ContextRecordInit, TestCase, SearchText): cr_2.operation = other_ope cr_2.save() rel_ope = models_ope.RelationType.objects.create( - symmetrical=True, label='Linked', txt_idx='link') + symmetrical=True, label="Linked", txt_idx="link" + ) models_ope.RecordRelations.objects.create( - left_record=other_ope, - right_record=first_ope, - relation_type=rel_ope) - rel_key = pgettext_lazy("key for text search", - "operation-relation-type") - response = c.get(reverse('get-contextrecord'), - {'operation__year': 2010, - rel_key: rel_ope.label}) - self.assertEqual(json.loads(response.content.decode())['recordsTotal'], - 2) + left_record=other_ope, right_record=first_ope, relation_type=rel_ope + ) + rel_key = pgettext_lazy("key for text search", "operation-relation-type") + response = c.get( + reverse("get-contextrecord"), + {"operation__year": 2010, rel_key: rel_ope.label}, + ) + self.assertEqual(json.loads(response.content.decode())["recordsTotal"], 2) # export - response = c.get(reverse('get-contextrecord-full', - kwargs={'type': 'csv'}), - {'submited': '1', - 'operation__year': 2010, rel_key: rel_ope.label}) - ENCODING = settings.ENCODING or 'utf-8' + response = c.get( + reverse("get-contextrecord-full", kwargs={"type": "csv"}), + {"submited": "1", "operation__year": 2010, rel_key: rel_ope.label}, + ) + ENCODING = settings.ENCODING or "utf-8" content = response.content.decode(ENCODING) # 2 lines + header - lines = [line for line in content.split('\n') if line] + lines = [line for line in content.split("\n") if line] self.assertEqual(len(lines), 3) def test_unit_hierarchic_search(self): cr = self.context_records[0] c = Client() - su = models.Unit.objects.get(txt_idx='stratigraphic-unit') - neg = models.Unit.objects.get(txt_idx='negative') - dest = models.Unit.objects.get(txt_idx='sector') + su = models.Unit.objects.get(txt_idx="stratigraphic-unit") + neg = models.Unit.objects.get(txt_idx="negative") + dest = models.Unit.objects.get(txt_idx="sector") dest.parent = su dest.save() - cr.unit = (neg) + cr.unit = neg cr.save() - search = {'unit': neg.pk} + search = {"unit": neg.pk} # no result when no authentication - response = c.get(reverse('get-contextrecord'), search) + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) content = response.content.decode() self.assertTrue(not json.loads(content)) # one result for exact search c.login(username=self.username, password=self.password) - response = c.get(reverse('get-contextrecord'), search) + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) res = json.loads(response.content.decode()) - self.assertEqual(res['recordsTotal'], 1) + self.assertEqual(res["recordsTotal"], 1) self.assertEqual(res["rows"][0]["unit__label"], str(neg)) # no result for the brother - search = {'unit': dest.pk} - response = c.get(reverse('get-contextrecord'), search) + search = {"unit": dest.pk} + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) content = response.content.decode() - self.assertEqual(json.loads(content)['recordsTotal'], 0) + self.assertEqual(json.loads(content)["recordsTotal"], 0) # one result for the father - search = {'unit': su.pk} - response = c.get(reverse('get-contextrecord'), search) + search = {"unit": su.pk} + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) content = response.content.decode() - self.assertEqual(json.loads(content)['recordsTotal'], 1) + self.assertEqual(json.loads(content)["recordsTotal"], 1) # test on text search - material_key = str(pgettext_lazy("key for text search", 'unit-type')) + material_key = str(pgettext_lazy("key for text search", "unit-type")) result = [ ('{}="{}"'.format(material_key, str(neg)), 1), ('{}="{}"'.format(material_key, str(dest)), 0), @@ -729,45 +738,43 @@ class ContextRecordSearchTest(ContextRecordInit, TestCase, SearchText): cr = self.context_records[0] c = Client() - neo = models.Period.objects.get(txt_idx='neolithic') - final_neo = models.Period.objects.get(txt_idx='final-neolithic') - recent_neo = models.Period.objects.get(txt_idx='recent-neolithic') - dating = models.Dating.objects.create( - period=final_neo - ) + neo = models.Period.objects.get(txt_idx="neolithic") + final_neo = models.Period.objects.get(txt_idx="final-neolithic") + recent_neo = models.Period.objects.get(txt_idx="recent-neolithic") + dating = models.Dating.objects.create(period=final_neo) cr.datings.add(dating) - search = {'datings__period': final_neo.pk} + search = {"datings__period": final_neo.pk} # no result when no authentication - response = c.get(reverse('get-contextrecord'), search) + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) content = response.content.decode() self.assertTrue(not json.loads(content)) # one result for exact search c.login(username=self.username, password=self.password) - response = c.get(reverse('get-contextrecord'), search) + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) res = json.loads(response.content.decode()) - self.assertTrue(res['recordsTotal'] == 1) + self.assertTrue(res["recordsTotal"] == 1) # no result for the brother - search = {'datings__period': recent_neo.pk} - response = c.get(reverse('get-contextrecord'), search) + search = {"datings__period": recent_neo.pk} + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) content = response.content.decode() - self.assertEqual(json.loads(content)['recordsTotal'], 0) + self.assertEqual(json.loads(content)["recordsTotal"], 0) # one result for the father - search = {'datings__period': neo.pk} - response = c.get(reverse('get-contextrecord'), search) + search = {"datings__period": neo.pk} + response = c.get(reverse("get-contextrecord"), search) self.assertEqual(response.status_code, 200) content = response.content.decode() - self.assertEqual(json.loads(content)['recordsTotal'], 1) + self.assertEqual(json.loads(content)["recordsTotal"], 1) # test on text search - period_key = str(pgettext_lazy("key for text search", 'datings-period')) + period_key = str(pgettext_lazy("key for text search", "datings-period")) result = [ ('{}="{}"'.format(period_key, str(final_neo)), 1), ('{}="{}"'.format(period_key, str(recent_neo)), 0), @@ -783,21 +790,23 @@ class ContextRecordPermissionTest(ContextRecordInit, TestCase): IshtarSiteProfile.objects.create() self.username, self.password, self.user = create_superuser() self.alt_username, self.alt_password, self.alt_user = create_user() - self.alt_user.user_permissions.add(Permission.objects.get( - codename='view_own_contextrecord')) - self.alt_user.user_permissions.add(Permission.objects.get( - codename='change_own_contextrecord')) + self.alt_user.user_permissions.add( + Permission.objects.get(codename="view_own_contextrecord") + ) + self.alt_user.user_permissions.add( + Permission.objects.get(codename="change_own_contextrecord") + ) self.alt_username2, self.alt_password2, self.alt_user2 = create_user( - username='luke', password='iamyourfather' + username="luke", password="iamyourfather" ) profile = UserProfile.objects.create( - profile_type=ProfileType.objects.get(txt_idx='collaborator'), + profile_type=ProfileType.objects.get(txt_idx="collaborator"), person=self.alt_user2.ishtaruser.person, - current=True + current=True, ) - town = Town.objects.create(name='Tatouine', numero_insee='66000') - area = Area.objects.create(label='Galaxie', txt_idx='galaxie') + town = Town.objects.create(name="Tatouine", numero_insee="66000") + area = Area.objects.create(label="Galaxie", txt_idx="galaxie") area.towns.add(town) profile.areas.add(area) @@ -807,70 +816,66 @@ class ContextRecordPermissionTest(ContextRecordInit, TestCase): self.operations += self.create_operation(self.alt_user, self.orgas[0]) self.operations[1].towns.add(town) - self.create_context_record(user=self.user, - data={"label": "CR 1", - "operation": self.operations[0]}) self.create_context_record( - user=self.alt_user, - data={"label": "CR 2", "operation": self.operations[1]}) + user=self.user, data={"label": "CR 1", "operation": self.operations[0]} + ) + self.create_context_record( + user=self.alt_user, data={"label": "CR 2", "operation": self.operations[1]} + ) self.cr_1 = self.context_records[0] self.cr_2 = self.context_records[1] def test_own_search(self): # no result when no authentification c = Client() - response = c.get(reverse('get-contextrecord')) + response = c.get(reverse("get-contextrecord")) self.assertTrue(not json.loads(response.content.decode())) # possession c = Client() c.login(username=self.alt_username, password=self.alt_password) - response = c.get(reverse('get-contextrecord')) + response = c.get(reverse("get-contextrecord")) # only one "own" context record available content = response.content.decode() self.assertTrue(json.loads(content)) - self.assertEqual(json.loads(content)['recordsTotal'], 1) + self.assertEqual(json.loads(content)["recordsTotal"], 1) # area filter c = Client() c.login(username=self.alt_username2, password=self.alt_password2) - response = c.get(reverse('get-contextrecord')) + response = c.get(reverse("get-contextrecord")) # only one "own" operation available content = response.content.decode() self.assertTrue(json.loads(content)) - self.assertEqual(json.loads(content)['recordsTotal'], 1) + self.assertEqual(json.loads(content)["recordsTotal"], 1) def test_own_modify(self): # no result when no authentification c = Client() - response = c.get(reverse('record_modify', args=[self.cr_2.pk])) + response = c.get(reverse("record_modify", args=[self.cr_2.pk])) self.assertRedirects(response, "/") - modif_url = '/record_modification/operation-record_modification' + modif_url = "/record_modification/operation-record_modification" # possession c = Client() c.login(username=self.alt_username, password=self.alt_password) - response = c.get(reverse('record_modify', args=[self.cr_2.pk]), - follow=True) + response = c.get(reverse("record_modify", args=[self.cr_2.pk]), follow=True) self.assertRedirects(response, modif_url) response = c.get(modif_url) self.assertEqual(response.status_code, 200) - response = c.get(reverse('record_modify', args=[self.cr_1.pk]), - follow=True) + response = c.get(reverse("record_modify", args=[self.cr_1.pk]), follow=True) self.assertRedirects(response, "/") # area filter c = Client() c.login(username=self.alt_username2, password=self.alt_password2) - response = c.get(reverse('record_modify', args=[self.cr_2.pk]), - follow=True) + response = c.get(reverse("record_modify", args=[self.cr_2.pk]), follow=True) self.assertRedirects(response, modif_url) response = c.get(modif_url) self.assertEqual(response.status_code, 200) - response = c.get(reverse('record_modify', args=[self.cr_1.pk]), - follow=True) + response = c.get(reverse("record_modify", args=[self.cr_1.pk]), follow=True) self.assertRedirects(response, "/") @@ -885,17 +890,21 @@ class RecordRelationsTest(ContextRecordInit, TestCase): def test_relations(self): sym_rel_type = models.RelationType.objects.create( - symmetrical=True, txt_idx='sym') + symmetrical=True, txt_idx="sym" + ) rel_type_1 = models.RelationType.objects.create( - symmetrical=False, txt_idx='rel_1') + symmetrical=False, txt_idx="rel_1" + ) # cannot be symmetrical and have an inverse_relation with self.assertRaises(ValidationError): rel_test = models.RelationType.objects.create( - symmetrical=True, inverse_relation=rel_type_1, txt_idx='rel_3') + symmetrical=True, inverse_relation=rel_type_1, txt_idx="rel_3" + ) rel_test.full_clean() # auto fill inverse relations rel_type_2 = models.RelationType.objects.create( - symmetrical=False, inverse_relation=rel_type_1, txt_idx='rel_2') + symmetrical=False, inverse_relation=rel_type_1, txt_idx="rel_2" + ) self.assertEqual(rel_type_1.inverse_relation, rel_type_2) cr_1 = self.context_records[0] @@ -904,119 +913,125 @@ class RecordRelationsTest(ContextRecordInit, TestCase): # inserting a new symmetrical relation automatically creates the same # relation for the second context record rel = models.RecordRelations.objects.create( - left_record=cr_1, right_record=cr_2, relation_type=sym_rel_type) - self.assertEqual(models.RecordRelations.objects.filter( - left_record=cr_2, right_record=cr_1, - relation_type=sym_rel_type).count(), 1) + left_record=cr_1, right_record=cr_2, relation_type=sym_rel_type + ) + self.assertEqual( + models.RecordRelations.objects.filter( + left_record=cr_2, right_record=cr_1, relation_type=sym_rel_type + ).count(), + 1, + ) # removing one symmetrical relation removes the other rel.delete() - self.assertEqual(models.RecordRelations.objects.filter( - left_record=cr_2, right_record=cr_1, - relation_type=sym_rel_type).count(), 0) + self.assertEqual( + models.RecordRelations.objects.filter( + left_record=cr_2, right_record=cr_1, relation_type=sym_rel_type + ).count(), + 0, + ) # for non-symmetrical relation, adding one relation automatically # adds the inverse rel = models.RecordRelations.objects.create( - left_record=cr_1, right_record=cr_2, relation_type=rel_type_1) - self.assertEqual(models.RecordRelations.objects.filter( - left_record=cr_2, right_record=cr_1, - relation_type=rel_type_2).count(), 1) + left_record=cr_1, right_record=cr_2, relation_type=rel_type_1 + ) + self.assertEqual( + models.RecordRelations.objects.filter( + left_record=cr_2, right_record=cr_1, relation_type=rel_type_2 + ).count(), + 1, + ) class ContextRecordWizardCreationTest(WizardTest, ContextRecordInit, TestCase): fixtures = OPERATION_TOWNS_FIXTURES - url_name = 'record_creation' - wizard_name = 'record_wizard' + url_name = "record_creation" + wizard_name = "record_wizard" steps = views.record_creation_steps - redirect_url = "/record_modification/selec-record_modification"\ - "?open_item={last_id}" + redirect_url = ( + "/record_modification/selec-record_modification" "?open_item={last_id}" + ) model = models.ContextRecord form_datas = [ FormData( "Create a simple context record", form_datas={ - 'selec': {}, - 'general': { - 'label': "First" - }, - 'relations': [], + "selec": {}, + "general": {"label": "First"}, + "relations": [], }, - ignored=('datings', - 'interpretation', - ) + ignored=( + "datings", + "interpretation", + ), ), FormData( "Create a context record with a relation and datings", form_datas={ - 'selec': {}, - 'general': { - 'label': "Second" - }, - 'relations': [], - 'datings': [] + "selec": {}, + "general": {"label": "Second"}, + "relations": [], + "datings": [], }, - ignored=('interpretation',) + ignored=("interpretation",), ), ] def pre_wizard(self): profile, created = IshtarSiteProfile.objects.get_or_create( - slug='default', active=True) + slug="default", active=True + ) profile.context_record = True profile.save() ope = self.get_default_operation() parcel = self.get_default_parcel() for form_data in self.form_datas: - form_data.set('selec', 'operation_id', ope.pk) - form_data.set('general', 'parcel', parcel.pk) + form_data.set("selec", "operation_id", ope.pk) + form_data.set("general", "parcel", parcel.pk) - self.related_cr = self.create_context_record(data={'operation': ope})[0] + self.related_cr = self.create_context_record(data={"operation": ope})[0] self.form_datas[1].append( - 'relations', - {'right_record': self.related_cr.pk, - 'relation_type': models.RelationType.objects.create( - label="Test", symmetrical=False).pk} + "relations", + { + "right_record": self.related_cr.pk, + "relation_type": models.RelationType.objects.create( + label="Test", symmetrical=False + ).pk, + }, ) period = models.Period.objects.all()[0].pk - self.form_datas[1].append( - 'datings', {'period': period} - ) - self.form_datas[1].append( - 'datings', {'period': period} - ) + self.form_datas[1].append("datings", {"period": period}) + self.form_datas[1].append("datings", {"period": period}) self.cr_nb = models.ContextRecord.objects.count() super(ContextRecordWizardCreationTest, self).pre_wizard() def post_wizard(self): - self.assertEqual(models.ContextRecord.objects.count(), - self.cr_nb + 2) - self.assertEqual(self.related_cr.left_relations.count(), - 1) + self.assertEqual(models.ContextRecord.objects.count(), self.cr_nb + 2) + self.assertEqual(self.related_cr.left_relations.count(), 1) # identical datings, only one should be finaly save - cr = models.ContextRecord.objects.order_by('-pk')[0] + cr = models.ContextRecord.objects.order_by("-pk")[0] self.assertEqual(cr.datings.count(), 1) class AutocompleteTest(AutocompleteTestBase, TestCase): fixtures = CONTEXT_RECORD_FIXTURES models = [ - AcItem(models.ContextRecord, 'autocomplete-contextrecord', - prepare_func="create_cr"), + AcItem( + models.ContextRecord, "autocomplete-contextrecord", prepare_func="create_cr" + ), ] def create_cr(self, base_name): ope, __ = models_ope.Operation.objects.get_or_create( - common_name="Test", - operation_type=models_ope.OperationType.objects.all()[0] + common_name="Test", operation_type=models_ope.OperationType.objects.all()[0] ) item, __ = models.ContextRecord.objects.get_or_create( - operation=ope, - label=base_name + operation=ope, label=base_name ) return item, None @@ -1026,11 +1041,14 @@ class GraphGenerationTest(ContextRecordInit, TestCase): def setUp(self): self.sym_rel_type, __ = models.RelationType.objects.get_or_create( - symmetrical=True, txt_idx='sym', logical_relation='equal') + symmetrical=True, txt_idx="sym", logical_relation="equal" + ) self.rel_type_below, __ = models.RelationType.objects.get_or_create( - symmetrical=False, txt_idx='below', logical_relation='below') + symmetrical=False, txt_idx="below", logical_relation="below" + ) self.rel_type_above, __ = models.RelationType.objects.get_or_create( - symmetrical=False, txt_idx='above', logical_relation='above') + symmetrical=False, txt_idx="above", logical_relation="above" + ) self.create_context_record({"label": "CR 1"}) self.create_context_record({"label": "CR 2"}) self.create_context_record({"label": "CR 3"}) @@ -1052,31 +1070,31 @@ class GraphGenerationTest(ContextRecordInit, TestCase): cr_2D = self.context_records[8] models.RecordRelations.objects.create( - left_record=cr_2, right_record=cr_2B, - relation_type=self.sym_rel_type) + left_record=cr_2, right_record=cr_2B, relation_type=self.sym_rel_type + ) models.RecordRelations.objects.create( - left_record=cr_1, right_record=cr_2, - relation_type=self.rel_type_below) + left_record=cr_1, right_record=cr_2, relation_type=self.rel_type_below + ) models.RecordRelations.objects.create( - left_record=cr_3, right_record=cr_2, - relation_type=self.rel_type_above) + left_record=cr_3, right_record=cr_2, relation_type=self.rel_type_above + ) models.RecordRelations.objects.create( - left_record=cr_3, right_record=cr_4, - relation_type=self.rel_type_below) + left_record=cr_3, right_record=cr_4, relation_type=self.rel_type_below + ) models.RecordRelations.objects.create( - left_record=cr_1B, right_record=cr_2B, - relation_type=self.rel_type_below) + left_record=cr_1B, right_record=cr_2B, relation_type=self.rel_type_below + ) models.RecordRelations.objects.create( - left_record=cr_3B, right_record=cr_2B, - relation_type=self.rel_type_above) + left_record=cr_3B, right_record=cr_2B, relation_type=self.rel_type_above + ) models.RecordRelations.objects.create( - left_record=cr_3B, right_record=cr_2C, - relation_type=self.rel_type_above) + left_record=cr_3B, right_record=cr_2C, relation_type=self.rel_type_above + ) models.RecordRelations.objects.create( - left_record=cr_2D, right_record=cr_3B, - relation_type=self.rel_type_below) + left_record=cr_2D, right_record=cr_3B, relation_type=self.rel_type_below + ) def test_gen_relation(self): generate_relation_graph(self.cr_2) @@ -1146,5 +1164,3 @@ class GraphGenerationTest(ContextRecordInit, TestCase): self.assertNotIn('"CR 4"', content) self.assertNotIn('"CR 2C"', content) self.assertNotIn('"CR 2D"', content) - - diff --git a/archaeological_context_records/urls.py b/archaeological_context_records/urls.py index 434aa79f9..be3994821 100644 --- a/archaeological_context_records/urls.py +++ b/archaeological_context_records/urls.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -28,76 +28,145 @@ from archaeological_context_records import views # forms urlpatterns = [ # Context records - url(r'record_search/(?P<step>.+)?$', - check_rights(['view_contextrecord', 'view_own_contextrecord'])( - views.record_search_wizard), name='record_search'), - url(r'contextrecord_search/(?P<step>.+)?$', - check_rights(['view_contextrecord', 'view_own_contextrecord'])( - views.record_search_wizard), name='contextrecord_search'), - url(r'record_creation/(?P<step>.+)?$', - check_rights(['add_contextrecord', 'add_own_contextrecord'])( - views.record_creation_wizard), name='record_creation'), - url(r'record_modification/(?P<step>.+)?$', - check_rights(['change_contextrecord', 'change_own_contextrecord'])( - views.record_modification_wizard), name='record_modification'), - url(r'record_modify/(?P<pk>.+)/$', - views.record_modify, name='record_modify'), - url(r'record_deletion/(?P<step>.+)?$', - check_rights(['change_contextrecord', 'change_own_contextrecord'])( - views.record_deletion_wizard), name='record_deletion'), - url(r'record_delete/(?P<pk>.+)/$', - views.record_delete, name='delete-contextrecord'), - url(r'autocomplete-contextrecord/$', views.autocomplete_contextrecord, - name='autocomplete-contextrecord'), - url(r'show-contextrecord(?:/(?P<pk>.+))?/(?P<type>.+)?$', - views.show_contextrecord, name=models.ContextRecord.SHOW_URL), + url( + r"record_search/(?P<step>.+)?$", + check_rights(["view_contextrecord", "view_own_contextrecord"])( + views.record_search_wizard + ), + name="record_search", + ), + url( + r"contextrecord_search/(?P<step>.+)?$", + check_rights(["view_contextrecord", "view_own_contextrecord"])( + views.record_search_wizard + ), + name="contextrecord_search", + ), + url( + r"record_creation/(?P<step>.+)?$", + check_rights(["add_contextrecord", "add_own_contextrecord"])( + views.record_creation_wizard + ), + name="record_creation", + ), + url( + r"record_modification/(?P<step>.+)?$", + check_rights(["change_contextrecord", "change_own_contextrecord"])( + views.record_modification_wizard + ), + name="record_modification", + ), + url(r"record_modify/(?P<pk>.+)/$", views.record_modify, name="record_modify"), + url( + r"record_deletion/(?P<step>.+)?$", + check_rights(["change_contextrecord", "change_own_contextrecord"])( + views.record_deletion_wizard + ), + name="record_deletion", + ), + url( + r"record_delete/(?P<pk>.+)/$", views.record_delete, name="delete-contextrecord" + ), + url( + r"autocomplete-contextrecord/$", + views.autocomplete_contextrecord, + name="autocomplete-contextrecord", + ), + url( + r"show-contextrecord(?:/(?P<pk>.+))?/(?P<type>.+)?$", + views.show_contextrecord, + name=models.ContextRecord.SHOW_URL, + ), # show-contextrecordrelation is only a view the id point to a context record - url(r'show-contextrecord(?:/(?P<pk>.+))?/(?P<type>.+)?$', - views.show_contextrecord, name='show-contextrecordrelation'), - url(r'show-historized-contextrecord/(?P<pk>.+)?/(?P<date>.+)?$', - views.show_contextrecord, name='show-historized-contextrecord'), - url(r'revert-contextrecord/(?P<pk>.+)/(?P<date>.+)$', - views.revert_contextrecord, name='revert-contextrecord'), - url(r'generate-relation-image-contextrecord/(?P<pk>.+)/(' - r'?P<type>(below)|(above)|(full))?', + url( + r"show-contextrecord(?:/(?P<pk>.+))?/(?P<type>.+)?$", + views.show_contextrecord, + name="show-contextrecordrelation", + ), + url( + r"show-historized-contextrecord/(?P<pk>.+)?/(?P<date>.+)?$", + views.show_contextrecord, + name="show-historized-contextrecord", + ), + url( + r"revert-contextrecord/(?P<pk>.+)/(?P<date>.+)$", + views.revert_contextrecord, + name="revert-contextrecord", + ), + url( + r"generate-relation-image-contextrecord/(?P<pk>.+)/(" + r"?P<type>(below)|(above)|(full))?", views.GenerateRelationImage.as_view(), - name='generate-relation-image-contextrecord'), - url(r'get-contextrecord/own/(?P<type>.+)?$', views.get_contextrecord, - name='get-own-contextrecord', kwargs={'force_own': True}), - url(r'get-contextrecord/(?P<type>.+)?$', views.get_contextrecord, - name='get-contextrecord'), - url(r'get-contextrecord-for-ope/own/(?P<type>.+)?$', + name="generate-relation-image-contextrecord", + ), + url( + r"get-contextrecord/own/(?P<type>.+)?$", + views.get_contextrecord, + name="get-own-contextrecord", + kwargs={"force_own": True}, + ), + url( + r"get-contextrecord/(?P<type>.+)?$", + views.get_contextrecord, + name="get-contextrecord", + ), + url( + r"get-contextrecord-for-ope/own/(?P<type>.+)?$", views.get_contextrecord_for_ope, - name='get-own-contextrecord-for-ope', kwargs={'force_own': True}), - url(r'get-contextrecord-for-ope/(?P<type>.+)?$', + name="get-own-contextrecord-for-ope", + kwargs={"force_own": True}, + ), + url( + r"get-contextrecord-for-ope/(?P<type>.+)?$", views.get_contextrecord_for_ope, - name='get-contextrecord-for-ope'), - url(r'get-contextrecord-full/own/(?P<type>.+)?$', - views.get_contextrecord, name='get-own-contextrecord-full', - kwargs={'full': True, 'force_own': True}), - url(r'get-contextrecord-full/(?P<type>.+)?$', - views.get_contextrecord, name='get-contextrecord-full', - kwargs={'full': True}), - url(r'get-contextrecord-shortcut/(?P<type>.+)?$', - views.get_contextrecord, name='get-contextrecord-shortcut', - kwargs={'full': 'shortcut'}), - url(r'get-contextrecordrelation/(?P<type>.+)?$', - views.get_contextrecordrelation, name='get-contextrecordrelation'), - url(r'get-contextrecordrelationdetail/(?P<type>.+)?$', + name="get-contextrecord-for-ope", + ), + url( + r"get-contextrecord-full/own/(?P<type>.+)?$", + views.get_contextrecord, + name="get-own-contextrecord-full", + kwargs={"full": True, "force_own": True}, + ), + url( + r"get-contextrecord-full/(?P<type>.+)?$", + views.get_contextrecord, + name="get-contextrecord-full", + kwargs={"full": True}, + ), + url( + r"get-contextrecord-shortcut/(?P<type>.+)?$", + views.get_contextrecord, + name="get-contextrecord-shortcut", + kwargs={"full": "shortcut"}, + ), + url( + r"get-contextrecordrelation/(?P<type>.+)?$", + views.get_contextrecordrelation, + name="get-contextrecordrelation", + ), + url( + r"get-contextrecordrelationdetail/(?P<type>.+)?$", views.get_contextrecordrelationdetail, - name='get-contextrecordrelationdetail'), - - url(r'^operation-qa-contextrecord/(?P<pks>[0-9]+)/$', - check_rights(['add_contextrecord', 'add_own_contextrecord'])( - views.QAOperationContextRecordView.as_view()), - name='operation-qa-contextrecord'), - - url(r'^contextrecord-qa-lock/(?P<pks>[0-9-]+)?/$', - views.QAContextRecordLockView.as_view(), name='contextrecord-qa-lock', - kwargs={"model": models.ContextRecord}), - url(r'^contextrecord-qa-duplicate/(?P<pks>[0-9-]+)?/$', - check_rights(['change_contextrecord', 'change_own_contextrecord'])( - views.QAContextRecordDuplicateFormView.as_view()), - name='contextrecord-qa-duplicate'), - + name="get-contextrecordrelationdetail", + ), + url( + r"^operation-qa-contextrecord/(?P<pks>[0-9]+)/$", + check_rights(["add_contextrecord", "add_own_contextrecord"])( + views.QAOperationContextRecordView.as_view() + ), + name="operation-qa-contextrecord", + ), + url( + r"^contextrecord-qa-lock/(?P<pks>[0-9-]+)?/$", + views.QAContextRecordLockView.as_view(), + name="contextrecord-qa-lock", + kwargs={"model": models.ContextRecord}, + ), + url( + r"^contextrecord-qa-duplicate/(?P<pks>[0-9-]+)?/$", + check_rights(["change_contextrecord", "change_own_contextrecord"])( + views.QAContextRecordDuplicateFormView.as_view() + ), + name="contextrecord-qa-duplicate", + ), ] diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py index 2de60dc2c..568d2a4f2 100644 --- a/archaeological_context_records/views.py +++ b/archaeological_context_records/views.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -34,139 +34,163 @@ from archaeological_operations.views import site_extra_context from archaeological_context_records import forms from ishtar_common.utils import put_session_message -from ishtar_common.views import IshtarMixin, LoginRequiredMixin, QAItemForm, \ - QABaseLockView, wizard_is_available -from ishtar_common.views_item import display_item, get_item, show_item, \ - revert_item +from ishtar_common.views import ( + IshtarMixin, + LoginRequiredMixin, + QAItemForm, + QABaseLockView, + wizard_is_available, +) +from ishtar_common.views_item import display_item, get_item, show_item, revert_item from archaeological_context_records import wizards show_contextrecord = show_item( - models.ContextRecord, 'contextrecord', - extra_dct=site_extra_context + models.ContextRecord, "contextrecord", extra_dct=site_extra_context ) revert_contextrecord = revert_item(models.ContextRecord) def autocomplete_contextrecord(request): - if (not request.user.has_perm( - 'archaeological_context_records.view_contextrecord', - models.ContextRecord) - and not request.user.has_perm( - 'archaeological_context_records.view_own_contextrecord', - models.ArchaeologicalSite)): - return HttpResponse(content_type='text/plain') - if not request.GET.get('term'): - return HttpResponse(content_type='text/plain') - q = request.GET.get('term') + if not request.user.has_perm( + "archaeological_context_records.view_contextrecord", models.ContextRecord + ) and not request.user.has_perm( + "archaeological_context_records.view_own_contextrecord", + models.ArchaeologicalSite, + ): + return HttpResponse(content_type="text/plain") + if not request.GET.get("term"): + return HttpResponse(content_type="text/plain") + q = request.GET.get("term") query = Q() - if request.GET.get('operation__pk'): - query = Q(operation__pk=request.GET.get('operation__pk')) - for q in q.split(' '): - qt = Q(parcel__section__icontains=q) | \ - Q(parcel__parcel_number__icontains=q) | \ - Q(cached_label__icontains=q) | Q(label__icontains=q) + if request.GET.get("operation__pk"): + query = Q(operation__pk=request.GET.get("operation__pk")) + for q in q.split(" "): + qt = ( + Q(parcel__section__icontains=q) + | Q(parcel__parcel_number__icontains=q) + | Q(cached_label__icontains=q) + | Q(label__icontains=q) + ) query = query & qt limit = 15 - items = models.ContextRecord.objects\ - .filter(query).order_by('parcel__section', 'parcel__parcel_number', - 'label')[:limit] - data = json.dumps([{'id': item.pk, - 'value': str(item)[:60]} - for item in items]) - return HttpResponse(data, content_type='text/plain') + items = models.ContextRecord.objects.filter(query).order_by( + "parcel__section", "parcel__parcel_number", "label" + )[:limit] + data = json.dumps([{"id": item.pk, "value": str(item)[:60]} for item in items]) + return HttpResponse(data, content_type="text/plain") get_contextrecord = get_item( models.ContextRecord, - 'get_contextrecord', 'contextrecord', - search_form=forms.RecordSelect + "get_contextrecord", + "contextrecord", + search_form=forms.RecordSelect, ) get_contextrecord_for_ope = get_item( models.ContextRecord, - 'get_contextrecord', 'contextrecord', - own_table_cols=models.ContextRecord.TABLE_COLS_FOR_OPE) + "get_contextrecord", + "contextrecord", + own_table_cols=models.ContextRecord.TABLE_COLS_FOR_OPE, +) get_contextrecordrelation = get_item( - models.RecordRelationView, 'get_contextrecordrelation', - 'contextrecordrelation', specific_perms=['view_recordrelation'], + models.RecordRelationView, + "get_contextrecordrelation", + "contextrecordrelation", + specific_perms=["view_recordrelation"], do_not_deduplicate=True, - extra_request_keys=models.RecordRelationView.EXTRA_REQUEST_KEYS + extra_request_keys=models.RecordRelationView.EXTRA_REQUEST_KEYS, ) get_contextrecordrelationdetail = get_item( - models.RecordRelations, 'get_contextrecordrelationdetail', - 'contextrecordrelationdetail', specific_perms=['view_recordrelation']) + models.RecordRelations, + "get_contextrecordrelationdetail", + "contextrecordrelationdetail", + specific_perms=["view_recordrelation"], +) -record_search_wizard = wizards.RecordSearch.as_view([ - ('general-record_search', forms.RecordFormSelection)], +record_search_wizard = wizards.RecordSearch.as_view( + [("general-record_search", forms.RecordFormSelection)], label=_("Context record search"), - url_name='record_search',) + url_name="record_search", +) record_creation_steps = [ - ('selec-record_creation', forms.OperationRecordFormSelection), - ('general-record_creation', forms.RecordFormGeneral), - ('datings-record_creation', forms.DatingFormSet), - ('interpretation-record_creation', forms.RecordFormInterpretation), - ('relations-record_creation', forms.RecordRelationsFormSet), - ('final-record_creation', forms.FinalForm) + ("selec-record_creation", forms.OperationRecordFormSelection), + ("general-record_creation", forms.RecordFormGeneral), + ("datings-record_creation", forms.DatingFormSet), + ("interpretation-record_creation", forms.RecordFormInterpretation), + ("relations-record_creation", forms.RecordRelationsFormSet), + ("final-record_creation", forms.FinalForm), ] record_creation_wizard = wizards.RecordWizard.as_view( record_creation_steps, label=_("New context record"), - url_name='record_creation', + url_name="record_creation", ) record_modification_steps = [ - ('selec-record_modification', forms.RecordFormSelection), - ('operation-record_modification', forms.OperationFormSelection), - ('general-record_modification', forms.RecordFormGeneral), - ('datings-record_modification', forms.DatingFormSet), - ('interpretation-record_modification', forms.RecordFormInterpretation), - ('relations-record_modification', forms.RecordRelationsFormSet), - ('final-record_modification', forms.FinalForm) + ("selec-record_modification", forms.RecordFormSelection), + ("operation-record_modification", forms.OperationFormSelection), + ("general-record_modification", forms.RecordFormGeneral), + ("datings-record_modification", forms.DatingFormSet), + ("interpretation-record_modification", forms.RecordFormInterpretation), + ("relations-record_modification", forms.RecordRelationsFormSet), + ("final-record_modification", forms.FinalForm), ] record_modification_wizard = wizards.RecordModifWizard.as_view( record_modification_steps, label=_("Context record modification"), - url_name='record_modification', + url_name="record_modification", ) def record_modify(request, pk): - if not wizard_is_available(record_modification_wizard, request, - models.ContextRecord, pk): + if not wizard_is_available( + record_modification_wizard, request, models.ContextRecord, pk + ): return HttpResponseRedirect("/") wizards.RecordModifWizard.session_set_value( - request, 'selec-record_modification', 'pk', pk, reset=True) - return redirect(reverse('record_modification', - kwargs={'step': 'operation-record_modification'})) - -record_deletion_wizard = wizards.RecordDeletionWizard.as_view([ - ('selec-record_deletion', forms.RecordFormMultiSelection), - ('final-record_deletion', forms.RecordDeletionForm)], + request, "selec-record_modification", "pk", pk, reset=True + ) + return redirect( + reverse("record_modification", kwargs={"step": "operation-record_modification"}) + ) + + +record_deletion_wizard = wizards.RecordDeletionWizard.as_view( + [ + ("selec-record_deletion", forms.RecordFormMultiSelection), + ("final-record_deletion", forms.RecordDeletionForm), + ], label=_("Context record deletion"), - url_name='record_deletion',) + url_name="record_deletion", +) def record_delete(request, pk): - if not wizard_is_available(record_deletion_wizard, request, - models.ContextRecord, pk): + if not wizard_is_available( + record_deletion_wizard, request, models.ContextRecord, pk + ): return HttpResponseRedirect("/") wizards.RecordDeletionWizard.session_set_value( - request, 'selec-record_deletion', 'pks', pk, reset=True) - return redirect(reverse('record_deletion', - kwargs={'step': 'final-record_deletion'})) + request, "selec-record_deletion", "pks", pk, reset=True + ) + return redirect( + reverse("record_deletion", kwargs={"step": "final-record_deletion"}) + ) def reset_wizards(request): for wizard_class, url_name in ( - (wizards.RecordWizard, 'record_creation'), - (wizards.RecordModifWizard, 'record_modification'), - (wizards.RecordDeletionWizard, 'record_deletion')): + (wizards.RecordWizard, "record_creation"), + (wizards.RecordModifWizard, "record_modification"), + (wizards.RecordDeletionWizard, "record_deletion"), + ): wizard_class.session_reset(request, url_name) @@ -176,28 +200,31 @@ class GenerateRelationImage(IshtarMixin, LoginRequiredMixin, RedirectView): def get_redirect_url(self, *args, **kwargs): if self.upper_item: - return reverse( - 'display-item', - args=[self.upper_model.SLUG, self.upper_item.pk]) + "#cr" - return reverse('display-item', - args=[self.model.SLUG, self.item.pk]) + "#relations" + return ( + reverse( + "display-item", args=[self.upper_model.SLUG, self.upper_item.pk] + ) + + "#cr" + ) + return ( + reverse("display-item", args=[self.model.SLUG, self.item.pk]) + "#relations" + ) def get(self, request, *args, **kwargs): self.upper_item = None render_type = kwargs.get("type", None) if render_type == "full" and self.upper_model: try: - self.upper_item = self.upper_model.objects.get(pk=kwargs['pk']) + self.upper_item = self.upper_model.objects.get(pk=kwargs["pk"]) except self.model.DoesNotExist: raise Http404() q = self.upper_item.context_record_relations_q() if not q.count(): - return super(GenerateRelationImage, self).get(request, *args, - **kwargs) + return super(GenerateRelationImage, self).get(request, *args, **kwargs) self.item = q.all()[0].left_record else: try: - self.item = self.model.objects.get(pk=kwargs['pk']) + self.item = self.model.objects.get(pk=kwargs["pk"]) except self.model.DoesNotExist: raise Http404() render_above, render_below, full = True, True, False @@ -208,21 +235,25 @@ class GenerateRelationImage(IshtarMixin, LoginRequiredMixin, RedirectView): elif render_type == "full": full = True self.item.generate_relation_image( - render_below=render_below, render_above=render_above, full=full) + render_below=render_below, render_above=render_above, full=full + ) return super(GenerateRelationImage, self).get(request, *args, **kwargs) class QAOperationContextRecordView(QAItemForm): - template_name = 'ishtar/forms/qa_operation_contextrecord.html' + template_name = "ishtar/forms/qa_operation_contextrecord.html" model = Operation form_class = forms.QAOperationCR page_name = _("Context record") def get_quick_action(self): return QuickAction( - url="operation-qa-contextrecord", icon_class="fa fa-plus", - text=_("Add context record"), target="one", - rights=['add_contextrecord', 'add_own_contextrecord']) + url="operation-qa-contextrecord", + icon_class="fa fa-plus", + text=_("Add context record"), + target="one", + rights=["add_contextrecord", "add_own_contextrecord"], + ) def form_valid(self, form): form.save(self.items) @@ -235,7 +266,7 @@ class QAContextRecordLockView(QABaseLockView): class QAContextRecordDuplicateFormView(QAItemForm): - template_name = 'ishtar/forms/qa_contextrecord_duplicate.html' + template_name = "ishtar/forms/qa_contextrecord_duplicate.html" model = models.ContextRecord page_name = _("Duplicate") form_class = forms.QAContextRecordDuplicateForm @@ -243,7 +274,7 @@ class QAContextRecordDuplicateFormView(QAItemForm): def get_form_kwargs(self): kwargs = super(QAContextRecordDuplicateFormView, self).get_form_kwargs() - kwargs['user'] = self.request.user + kwargs["user"] = self.request.user return kwargs def form_valid(self, form): @@ -251,8 +282,7 @@ class QAContextRecordDuplicateFormView(QAItemForm): return HttpResponseRedirect(reverse("success")) def get_context_data(self, **kwargs): - data = super(QAContextRecordDuplicateFormView, self).get_context_data( - **kwargs) - data['action_name'] = _("Duplicate") + data = super(QAContextRecordDuplicateFormView, self).get_context_data(**kwargs) + data["action_name"] = _("Duplicate") data["operation"] = self.items[0].operation return data diff --git a/archaeological_context_records/wizards.py b/archaeological_context_records/wizards.py index 53f13c481..da1364b28 100644 --- a/archaeological_context_records/wizards.py +++ b/archaeological_context_records/wizards.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2012-2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -32,15 +32,15 @@ class RecordSearch(SearchWizard): class RecordWizard(Wizard): model = models.ContextRecord edit = False - wizard_done_window = reverse_lazy('show-contextrecord') - relations_step_key = 'relations' - redirect_url = 'record_modification' + wizard_done_window = reverse_lazy("show-contextrecord") + relations_step_key = "relations" + redirect_url = "record_modification" def get_template_names(self): templates = super(RecordWizard, self).get_template_names() current_step = self.steps.current if current_step.startswith(self.relations_step_key): - templates = ['ishtar/wizard/relations_wizard.html'] + templates + templates = ["ishtar/wizard/relations_wizard.html"] + templates return templates def get_current_operation(self): @@ -48,23 +48,21 @@ class RecordWizard(Wizard): if not step: return # manage manualy on creation - if step.endswith('_creation'): # an operation has been selected - main_form_key = 'selec-' + self.url_name + if step.endswith("_creation"): # an operation has been selected + main_form_key = "selec-" + self.url_name try: - idx = int(self.session_get_value( - main_form_key, 'operation_id')) + idx = int(self.session_get_value(main_form_key, "operation_id")) current_ope = models.Operation.objects.get(pk=idx) return current_ope - except(TypeError, ValueError, ObjectDoesNotExist): + except (TypeError, ValueError, ObjectDoesNotExist): pass else: - ope_form_key = 'operation-' + self.url_name + ope_form_key = "operation-" + self.url_name try: - idx = int(self.session_get_value( - ope_form_key, 'operation')) + idx = int(self.session_get_value(ope_form_key, "operation")) current_ope = models.Operation.objects.get(pk=idx) return current_ope - except(TypeError, ValueError, ObjectDoesNotExist): + except (TypeError, ValueError, ObjectDoesNotExist): pass current_cr = self.get_current_object() if current_cr: @@ -77,9 +75,9 @@ class RecordWizard(Wizard): context = super(RecordWizard, self).get_context_data(form) operation = self.get_current_operation() - if not operation or self.steps.current.startswith('selec-'): + if not operation or self.steps.current.startswith("selec-"): return context - context['reminders'] = ((_("Operation"), str(operation)),) + context["reminders"] = ((_("Operation"), str(operation)),) return context def get_form(self, step=None, data=None, files=None): @@ -96,30 +94,28 @@ class RecordWizard(Wizard): form = self.get_form_list()[step] # general_form_key = 'general-' + self.url_name - if step.startswith('general-'): - if step.endswith('_creation'): # an operation has been selected - main_form_key = 'selec-' + self.url_name + if step.startswith("general-"): + if step.endswith("_creation"): # an operation has been selected + main_form_key = "selec-" + self.url_name try: - idx = int(self.session_get_value(main_form_key, - 'operation_id')) + idx = int(self.session_get_value(main_form_key, "operation_id")) current_obj = models.Operation.objects.get(pk=idx) - data['operation'] = current_obj - except(TypeError, ValueError, ObjectDoesNotExist): + data["operation"] = current_obj + except (TypeError, ValueError, ObjectDoesNotExist): pass - elif step.endswith('_modification'): - ope_form_key = 'operation-' + self.url_name + elif step.endswith("_modification"): + ope_form_key = "operation-" + self.url_name try: - idx = int(self.session_get_value(ope_form_key, - 'operation')) + idx = int(self.session_get_value(ope_form_key, "operation")) current_obj = models.Operation.objects.get(pk=idx) - data['operation'] = current_obj - except(TypeError, ValueError, ObjectDoesNotExist): + data["operation"] = current_obj + except (TypeError, ValueError, ObjectDoesNotExist): pass else: current_object = self.get_current_object() - data['context_record'] = current_object - elif step.startswith('relations') and hasattr(form, 'management_form'): - data['CONTEXT_RECORDS'] = self.get_other_context_records() + data["context_record"] = current_object + elif step.startswith("relations") and hasattr(form, "management_form"): + data["CONTEXT_RECORDS"] = self.get_other_context_records() form = super(RecordWizard, self).get_form(step, data, files) return form @@ -137,11 +133,10 @@ class RecordWizard(Wizard): class RecordModifWizard(RecordWizard): modification = True model = models.ContextRecord - filter_owns = {'selec-record_modification': ['pk']} + filter_owns = {"selec-record_modification": ["pk"]} def get_form_kwargs(self, step, **kwargs): - kwargs = super(RecordModifWizard, self).get_form_kwargs( - step, **kwargs) + kwargs = super(RecordModifWizard, self).get_form_kwargs(step, **kwargs) if step != "relations-record_modification": return kwargs kwargs["left_record"] = self.get_current_object() @@ -150,9 +145,24 @@ class RecordModifWizard(RecordWizard): class RecordDeletionWizard(MultipleDeletionWizard): model = models.ContextRecord - fields = ['label', 'parcel', 'description', 'length', 'width', 'thickness', - 'depth', 'location', 'datings', 'units', 'documentations', - 'filling', 'interpretation', 'taq', 'taq_estimated', 'tpq', - 'tpq_estimated'] - filter_owns = {'selec-record_deletion': ['pks']} + fields = [ + "label", + "parcel", + "description", + "length", + "width", + "thickness", + "depth", + "location", + "datings", + "units", + "documentations", + "filling", + "interpretation", + "taq", + "taq_estimated", + "tpq", + "tpq_estimated", + ] + filter_owns = {"selec-record_deletion": ["pks"]} redirect_url = "record_deletion" |