diff options
Diffstat (limited to 'archaeological_operations/import_from_csv.py')
-rw-r--r-- | archaeological_operations/import_from_csv.py | 146 |
1 files changed, 112 insertions, 34 deletions
diff --git a/archaeological_operations/import_from_csv.py b/archaeological_operations/import_from_csv.py index 9d3a58ffd..d00327cef 100644 --- a/archaeological_operations/import_from_csv.py +++ b/archaeological_operations/import_from_csv.py @@ -36,7 +36,7 @@ from ishtar_common.models import Town, Person, PersonType, OrganizationType, \ Organization, SourceType from archaeological_files.models import PermitType, File, FileType from archaeological_operations.models import Operation, OperationType, Period, \ - AdministrativeAct, ActType, OperationSource + AdministrativeAct, ActType, OperationSource, Parcel DEFAULT_PERSON = User.objects.order_by('pk').all()[0] @@ -410,6 +410,44 @@ def parse_rapp_index(value): if items: return int(items[-1]) +PARCEL_YEAR_REGEXP = re.compile(r"^([0-9]{4})[ :]+") +PARCEL_SECTION_REGEXP = re.compile(ur"(?: )*(?:[Ss]ection(?:s)?)?(?: )*([A-Z][A-Z0-9]{0,3})[ :]*((?:(?: |;|,|[Pp]arcelle(?:s)?|n°|et|à)*[0-9]+[p]?)+)") +PARCEL_NB_RANGE_REGEXP = re.compile(ur'([0-9]+[p]?) à ([0-9]+[p]?)') +PARCEL_NB_REGEXP = re.compile(ur'(?: |;|,|[Pp]arcelle(?:s)?|n°|et|à)*([0-9]+[p]?)') + +def parse_parcels(parcel_str, insee_code, owner): + parcels = [] + town = parse_insee(insee_code) + # manage only one town at a time + assert len(town) < 2 + if not town: + return parcels + town = town[0] + m = PARCEL_YEAR_REGEXP.match(parcel_str) + year = None + if m: + year = m.groups()[0] + parcel_str = parcel_str[m.span()[1]:] + for parcel in PARCEL_SECTION_REGEXP.findall(parcel_str): + sector, nums = parcel[0], parcel[1] + print PARCEL_NB_REGEXP.findall(nums) + for num in PARCEL_NB_REGEXP.findall(nums): + parcels.append({'year':year, 'town':town, 'section':sector, + 'parcel_number':num, 'history_modifier':owner}) + for parcel_ranges in PARCEL_NB_RANGE_REGEXP.findall(nums): + lower_range, higher_range = parcel_ranges + try: + # the lower range itself has been already kept + lower_range = int(lower_range) + 1 + higher_range = int(higher_range) + except ValueError: + continue + for num in xrange(lower_range, higher_range): + parcels.append({'year':year, 'town':town, + 'section':sector, 'parcel_number':unicode(num), + 'history_modifier':owner}) + return parcels + _CACHED_DOC_TYPES = {} def parse_doc_types(value): @@ -462,7 +500,6 @@ for cols in _OPE_COLS: else: OPE_COLS.append(None) - def ope_postimportfix(ope, dct): changed = False if not ope.year: @@ -478,10 +515,15 @@ def ope_postimportfix(ope, dct): ope.save() return ope +class BreakIt(Exception): + pass + class RelatedClass: - def __init__(self, key, cls, default_data={}, reverse_key=False, unique_keys=[]): + def __init__(self, key, cls, default_data={}, reverse_key=False, + unique_keys=[], extra_data=[], multi=None): self.key, self.cls, self.default_data = key, cls, default_data self.reverse_key, self.unique_keys = reverse_key, unique_keys + self.extra_data, self.multi = extra_data, multi def create_object(self, data): if self.unique_keys: @@ -490,25 +532,39 @@ class RelatedClass: unique_data[k] = data.pop(k) unique_data['defaults'] = data obj, created = self.cls.objects.get_or_create(**unique_data) + if not created: + for k in unique_data['defaults']: + setattr(obj, k, unique_data['defaults'][k]) + obj.save() else: obj = self.cls.objects.create(**data) return obj def create(self, item, data, attr=None): - if self.reverse_key: - data[self.reverse_key] = item - obj = self.create_object(data) - else: - obj = getattr(item, attr) - if not obj: + datas = data + if not self.multi: + datas = [data] + objs = [] + for data in datas: + if self.reverse_key: + data[self.reverse_key] = item + if self.reverse_key not in self.unique_keys: + self.unique_keys.append(self.reverse_key) obj = self.create_object(data) - setattr(item, attr, obj) - item.save() else: - for k in data: - setattr(obj, k, data[k]) - obj.save() - return obj + obj = getattr(item, attr) + if not obj: + obj = self.create_object(data) + setattr(item, attr, obj) + item.save() + else: + for k in data: + setattr(obj, k, data[k]) + obj.save() + objs.append(obj) + if not self.multi: + return objs[0] + return objs #@transaction.commit_manually def import_operations_csv(values, col_defs=OPE_COLS, update=True, person=None, @@ -523,11 +579,17 @@ def import_operations_csv(values, col_defs=OPE_COLS, update=True, person=None, reverse_key='operation', unique_keys=['ref_sra']), RelatedClass('associated_file', File, + extra_data=['year'], default_data={'history_modifier':default_person, 'file_type':FileType.objects.get( - txt_idx='undefined')}), + txt_idx='undefined')}, + unique_keys=['internal_reference']), RelatedClass('source', OperationSource, reverse_key='operation', unique_keys=['index']), + RelatedClass('parcels', Parcel, reverse_key='operation', + unique_keys=['operation', 'town', 'section', + 'parcel_number'], + multi=True), ] RELATED_CLASSES_KEYS = dict([(rel_cls.key, rel_cls) for rel_cls in RELATED_CLASSES]) @@ -575,11 +637,11 @@ def import_operations_csv(values, col_defs=OPE_COLS, update=True, person=None, if not extra_cols: v = typ(val) else: - arguments = [vals[col_number] for col_number in extra_cols] - if not [arg for arg in arguments if arg]: - continue - arguments += [default_person] - v = typ(val, *arguments) + arguments = [vals[col_number] for col_number in extra_cols] + if not [arg for arg in arguments if arg]: + continue + arguments += [default_person] + v = typ(val, *arguments) except: v = None if len(attrs) == 1: @@ -605,19 +667,35 @@ def import_operations_csv(values, col_defs=OPE_COLS, update=True, person=None, multis = [] attached_models = {} for k in args.keys(): - if k in related_classes: - rel_cls = related_classes[k] - cls, default = rel_cls.cls, rel_cls.default_data - reverse_key = rel_cls.reverse_key - default.update(args[k]) - args.pop(k) - related_items.append((rel_cls, default.copy(), k)) - elif type(args[k]) == list or k in multi_keys: - multis.append((k, args[k])) - args.pop(k) - elif '__' in k: - mod, value = k.split('__') - attached_models[(mod, value)] = args.pop(k) + try: + if k in related_classes: + rel_cls = related_classes[k] + cls, default = rel_cls.cls, rel_cls.default_data + reverse_key = rel_cls.reverse_key + values = None + if rel_cls.multi: + values = [] + for v in args[k]: + v.update(default) + values.append(v) + else: + values = default.copy() + values.update(args[k]) + exited = False + for extra in rel_cls.extra_data: + if not args.get(extra): + raise BreakIt + values[extra] = args[extra] + args.pop(k) + related_items.append((rel_cls, values, k)) + elif k in multi_keys: + multis.append((k, args[k])) + args.pop(k) + elif '__' in k: + mod, value = k.split('__') + attached_models[(mod, value)] = args.pop(k) + except BreakIt: + continue op = None if not update and not args.get('operation_type'): #print "Pas d'operation_type" |