def test_parsedate_timezone(self): tab_format_date = [ '2015-01-01', '20150101', '01-01-2015', '01/01/2015', '2015/01/01' ] for format_date in tab_format_date: self.assertEqual( parsedate(format_date).tzinfo.zone, settings.TIME_ZONE)
def test_parsedate_format_date(self): tab_format_date = [ '2015-01-01', '20150101', '01-01-2015', '01/01/2015', '2015/01/01' ] for format_date in tab_format_date: self.assertIsInstance(parsedate(format_date, date_only=True), datetime.date)
def test_parsedate_utc(self): tab_format_date = [ '2015-01-01', '20150101', '01-01-2015', '01/01/2015', '2015/01/01' ] for format_date in tab_format_date: self.assertEqual( parsedate(format_date, utc=True).tzinfo.zone, 'UTC')
def test_parsedatetime_datetime(self): tab_format_datetime = [ '2015-01-01 18:25:52', '20150101 18:25:52', '01-01-2015 18:25:52', '01/01/2015 18:25:52', '2015/01/01 18:25:52' ] for format_datetime in tab_format_datetime: self.assertIsInstance(parsedate(format_datetime), datetime.datetime)
def filter_parsedate(value, options=''): """ Parse une date ou un datetime dans n'importe quel format :param value: Date ou datetime au format texte :param options: Options de parsing (au format query string) :return: Date ou datetime """ from common.utils import parsedate options = QueryDict(options) return parsedate(value, **options)
def wrapper(item, *args, **kwargs): # "request = item.request" dans le cas d'une ViewSet, "item" dans le cas d'une api_view request = item.request if hasattr(item, 'request') else item valid = None valid_date = None params = request.data if request.data else request.query_params if params: valid = str_to_bool(params.get('valid', None)) valid_date = parsedate(params.get('valid_date', None)) setattr(request, 'valid', valid) setattr(request, 'valid_date', valid_date) setattr(request, 'valid_filter', dict(valid=valid, date=valid_date)) return func(item, *args, **kwargs)
def test_parsedate_initial(self): tab_format_date = [ '2015-01-01', '20150101', '01-01-2015', '01/01/2015', '2015/01/01' ] for format_date in tab_format_date: self.assertEqual(parsedate(format_date).year, 2015) self.assertEqual(parsedate(format_date).month, 1) self.assertEqual(parsedate(format_date).day, 1) self.assertEqual(parsedate(format_date).hour, 0) self.assertEqual(parsedate(format_date).minute, 0) self.assertEqual(parsedate(format_date).second, 0) self.assertEqual(parsedate(format_date).microsecond, 0)
def test_parsedate_end_day(self): tab_format_date = [ '2015-01-01', '20150101', '01-01-2015', '01/01/2015', '2015/01/01' ] for format_date in tab_format_date: self.assertEqual(parsedate(format_date).year, 2015) self.assertEqual(parsedate(format_date).month, 1) self.assertEqual(parsedate(format_date).day, 1) self.assertEqual(parsedate(format_date, end_day=True).hour, 23) self.assertEqual(parsedate(format_date, end_day=True).minute, 59) self.assertEqual(parsedate(format_date, end_day=True).second, 59) self.assertEqual( parsedate(format_date, end_day=True).microsecond, 999999)
def test_parsedatetime(self): tab_format_date = ['2015-01-01 150205', '20150101 15:02:05'] for format_date in tab_format_date: self.assertEqual(parsedate(format_date).year, 2015) self.assertEqual(parsedate(format_date).month, 1) self.assertEqual(parsedate(format_date).day, 1) self.assertEqual( parsedate(format_date, start_day=True, end_day=True).hour, 15) self.assertEqual( parsedate(format_date, start_day=True, end_day=True).minute, 2) self.assertEqual( parsedate(format_date, start_day=True, end_day=True).second, 5) self.assertEqual( parsedate(format_date, start_day=True, end_day=True).microsecond, 0)
def importer(self, file): """ Importe les données d'un document Excel de tarification :param file: Chemin vers le document Excel :return: Cache """ cache = {} metadata = {} workbook = load_workbook(filename=file, read_only=True, data_only=True) # Récupération de toutes les feuilles par nom worksheets = {} for worksheet in workbook.worksheets: worksheets[worksheet.title.lower()] = worksheet # Si elle existe, nous traitons la feuille des métadonnées metadata_sheet_name = str(METADATA_NAME) if metadata_sheet_name in worksheets: worksheet = worksheets.get(metadata_sheet_name) headers = {} title = True for row_number, row in enumerate(worksheet.iter_rows()): code_meta = '' line = [] for col_number, cell in enumerate(row): value = cell.value if isinstance(value, str): value = value.strip() if value is None or not str(value).strip(): continue # Si c'est la ligne des titres, on ne récupère que les données liées aux colonnes if title: value = value.lower() headers[col_number] = value continue field = headers[col_number] if field == 'code': if value not in metadata: metadata[value] = [] code_meta = value continue line.append(value) # Si c'est la ligne des titres, on n'enregistre aucune donnée if title: title = False continue metadata[code_meta].append(line) done = [] for model in self.models: code_field = getattr(model, '_code_field', 'id') # Retrait des espaces et des caractères superflus model_name = re.sub(r'[^\w]+', ' ', str(model._meta.verbose_name).lower()) # Récupération de la feuille correspondante au modèle if model_name not in worksheets: self.log.warning( _("La feuille correspondant au modèle '{model_name}' " "n'a pu être trouvée dans le fichier.").format( model_name=model_name)) continue worksheet = worksheets.get(model_name) # Récupération des champs du modèle fields = {} for field in chain(model._meta.fields, model._meta.many_to_many): if field.name != code_field and ( field.auto_created or not (field.editable or self.non_editables)): continue field.m2m = field in model._meta.many_to_many fields[str(field.verbose_name).lower()] = field # Parcours des lignes de la feuille self.delayed_models = [] headers = {} title = True for row_number, row in enumerate(worksheet.iter_rows()): instance = model() current_metadata = {} delayed = False m2m = {} fks = {} # Parcours des cellules de la ligne has_data = False for col_number, cell in enumerate(row): # Récupération de la valeur de la cellule, ignorée si vide value = cell.value if isinstance(value, str): value = value.strip() if value is None or not str(value).strip(): continue # Si c'est la ligne des titres, on ne récupère que les données liées aux colonnes if title: value = value.lower() if value in fields: headers[col_number] = fields[value] continue # Si la colonne n'est pas référencée comme un champ connu, elle est ignorée if col_number not in headers: continue field = headers[col_number] # Gestion des types spécifiques mal gérés par Excel type = field.get_internal_type() if field.m2m: if field.related_model == model: delayed = True value = [v.strip() for v in value.split(',')] m2m[field.name] = (field.related_model, value) has_data = True continue elif field.remote_field is not None and field.related_model is MetaData: current_metadata = dict(metadata.get(value, [])) continue elif field.remote_field: if field.related_model == model: delayed = True fks[field.name] = (field.related_model, value) has_data = True continue elif field.choices: choices = { str(value): str(key) for key, value in field.flatchoices } if hasattr(field, 'max_choices'): # MultiSelectField value = [ choices[val] for val in choices.keys() if val in value ] else: value = choices[value] elif type in ['DateField', 'DateTimeField']: value = parsedate(value, dayfirst=True) elif type == 'DecimalField': value = decimal(value, precision=20) elif type == 'BooleanField': value = str_to_bool(value) has_data = True # Récupération des données existantes if field.name == code_field and field.unique: existing = model.objects.filter(**{code_field: value}) if existing.count() == 1: instance = existing.first() # Modification des propriétés du modèle setattr(instance, field.name, value) # Si c'est la ligne des titres, on n'enregistre aucune donnée if title: title = False continue # Si la ligne est vide, on passe à la suivante if not has_data: continue # Mise en cache de l'instance courante code = getattr(instance, code_field, id(instance)) if model not in cache: cache[model] = {} cache[model][code] = instance # Enregistrement immédiat (si possible) if delayed: self.delayed_models.append( (instance, fks, m2m, current_metadata)) continue self._save_instance(instance, metadata=current_metadata, cache=cache, fks=fks, m2m=m2m) # Enregistrement différé for instance, fks, m2m, current_metadata in self.delayed_models: self._save_instance(instance, metadata=current_metadata, cache=cache, fks=fks, m2m=m2m) # Intégration terminée done.append(model) return cache
def test_obj_datetime_ok(self): from datetime import datetime self.assertIsInstance(parsedate(datetime(2000, 1, 1)), datetime) self.assertEqual(parsedate(datetime(2000, 1, 1)).year, 2000) self.assertEqual(parsedate(datetime(2000, 1, 1)).month, 1) self.assertEqual(parsedate(datetime(2000, 1, 1)).day, 1)
def test_parsedate_isoformat_yyyymmdd(self): format_date = '20030925' self.assertIsInstance(parsedate(format_date), datetime.datetime)
def test_parsedate_isoformat_yyyymmddthhmmsstz(self): format_date = '20030925T104941-0300' self.assertIsInstance(parsedate(format_date), datetime.datetime)
def test_parsedate_bisextil_ko(self): format_date = '2015-02-29' self.assertIsNone(parsedate(format_date))
def test_parsedate_ecrit_yyyy(self): format_date = '2003' self.assertIsInstance(parsedate(format_date), datetime.datetime)
def test_parsedate_ecrit_mmm(self): format_date = 'Dec' self.assertIsInstance(parsedate(format_date), datetime.datetime)
def _write_model(self, workbook, model): """ Ecrit le modèle dans un document Excel ouvert :param workbook: Document Excel :param model: Modèle :return: Rien """ meta = model._meta code_field = getattr(model, '_code_field', 'id') worksheet = workbook.create_sheet( title=re.sub(r'[^\w]+', ' ', str(meta.verbose_name).capitalize())) widths = {} dropdowns = {} # Titres fields = [ ( field.name, str(field.verbose_name), ) for field in chain(meta.fields, meta.many_to_many) if field.name == code_field or not (field.auto_created or not ( field.editable or self.non_editables)) ] for column, (field_code, field_name) in enumerate(fields, start=1): cell = worksheet.cell(row=1, column=column) cell.value = field_name cell.font = self.title_font column_letter = get_column_letter(column) widths[column_letter] = len(str(cell.value)) + CELL_OFFSET # Récupération des données queryset = model.objects.select_related().order_by(code_field) row = 2 for element in queryset: for column, (field_code, field_name) in enumerate(fields, start=1): value = getattr(element, field_code) if value is None: continue field = meta.get_field(field_code) if field.many_to_many: m2m_code_field = getattr(field.related_model, '_code_field', 'id') value = ', '.join( str(v) for v in value.values_list(m2m_code_field, flat=True)) elif field.related_model is not None and field.related_model is MetaData: if len(element.get_metadata()) > 0: value = 'meta_{}_{}'.format(element._meta.model_name, row) self.metadata[value] = [] for key_meta, value_meta in element.get_metadata( ).items(): self.metadata[value].append(( key_meta, value_meta, )) else: continue elif field.remote_field: if not value: value = '' else: value = getattr(value, code_field, value.id) elif field.choices: value = getattr(element, 'get_{}_display'.format(field_code))() if column not in dropdowns: data_validation = dropdowns[column] = self.dropdowns[ model, field_code] worksheet.add_data_validation(data_validation) dropdowns[column].add(worksheet["{}{}".format( get_column_letter(column), row)]) elif field.get_internal_type() in [ 'DateField', 'DateTimeField' ]: value = parsedate(value).isoformat() elif isinstance(value, FieldFile): value = value.name elif isinstance(value, dict): value = json_encode(value) cell = worksheet.cell(row=row, column=column) try: cell.value = value except Exception: cell.value = str(value) column_letter = get_column_letter(column) widths[column_letter] = max(widths[column_letter], len(str(value)) + CELL_OFFSET) row += 1 # Ajout de lignes vides avec listes déroulantes for row in range(row, row + 10): for column, (field_code, field_name) in enumerate(fields, start=1): field = meta.get_field(field_code) if not field.choices: continue if column not in dropdowns: data_validation = dropdowns[column] = self.dropdowns[ model, field_code] worksheet.add_data_validation(data_validation) dropdowns[column].add(worksheet["{}{}".format( get_column_letter(column), row)]) # Redimensionne les colonnes for column_letter, width in widths.items(): worksheet.column_dimensions[column_letter].width = width
def test_parsedate_ecrit_dddddmmyyyy(self): format_date = 'Thu, 25 Dec 2003' self.assertIsInstance(parsedate(format_date), datetime.datetime)
def test_parsedate_format_ko(self): format_date = '01012016' self.assertIsNone(parsedate(format_date))
def test_parsedate_bisextil_ok(self): format_date = '2016-02-29' self.assertIsInstance(parsedate(format_date), datetime.datetime)
def test_parsedate_none(self): self.assertIsNone(parsedate('chaine'))
def test_parsedate_ecrit_dddddmmyyyyhhmmss(self): format_date = 'Thu, 25 Dec 2003 10:49:41 -0300' self.assertIsInstance(parsedate(format_date), datetime.datetime)
def test_parsedate_ecrit_yyyymmddthhmmssxtz(self): format_date = '2003-09-25T10:49:41.5-03:00' self.assertIsInstance(parsedate(format_date), datetime.datetime)