def __init__(self, *args, **kwargs): null = kwargs.get('null', False) default = kwargs.get('default', None) self.encoder = kwargs.get('encoder', None) if not null and default is None: kwargs['default'] = {} if isinstance(default, (list, dict)): json_encode(default) kwargs['default'] = default models.Field.__init__(self, *args, **kwargs)
def validate(self, value, model_instance): super().validate(value, model_instance) try: json_encode(value, cls=self.encoder) except TypeError: raise ValidationError( self.error_messages['invalid'], code='invalid', params={'value': value}, )
def view_cache(request): """ Cache """ value = None key = request.GET.get('key', None) if key: value = cache.get(key) try: value = dict(value) value = json_encode(value, indent=4) except (TypeError, ValueError): pass if hasattr(cache, 'keys'): for key in request.POST: cache.delete_pattern(key) keys = sorted(cache.keys('*')) else: for key in request.POST: cache.delete(key) keys = sorted((key.split(':')[-1] for key in cache._cache.keys())) return { 'keys': keys, 'value': value or None, }
def create_auto_test_class(fixture, callback): """ Crée un test automatisé à partir d'une fixture complète :param fixture: Chemin vers la fixture :param callback: Fonction retournant les résultats à vérifier :return: Classe de test """ import os import tempfile import decimal # Classe de test transactionnelle supprimant la fixture à la fin class AutoTest(Test): @classmethod def tearDownClass(cls): for fixture in cls.fixtures: os.remove(fixture) super().tearDownClass() # Récupération du nom depuis le fichier name, ext = os.path.splitext(os.path.basename(fixture)) name = ''.join(x.capitalize() or '_' for x in name.split('_')) + 'TestCase' # Lecture des données with open(fixture, 'r') as file: data = json_decode(file.read()) # Création d'une fixture temporaire à partir des modèles models = data.pop('models', {}) with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', delete=False, suffix='.json') as temp_file: temp_file.write(json_encode(models)) temp_file.flush() # Création de la classe de test test_class = type(name, (AutoTest, ), dict(data=data, fixtures=[temp_file.name])) # Création des méthodes de test tests = data.pop('tests') for index, test in enumerate(tests, start=1): def test_method(self, test=test): data = callback(test) with self.subTest(): for result in test.get('results', []): fields = result.get('fields', []) value = result.get('value', None) current = data for field in fields: current = current[field] # Conversion explicite en décimal if isinstance(current, decimal.Decimal): value = decimal.Decimal(str(value)) operator = OPERATORS.get(result.get('operator', '==')) operator(self, current, value) test_name = 'test_{}'.format( slugify(test.get('name', index)).replace('-', '_')) setattr(test_class, test_name, test_method) return test_class
def create_auto_test_class(fixture, callback): """ Creates an automated test from a complete fixture :param fixture: Path to the fixture :param callback: Function returning results to be verified :return: Test class """ import os import tempfile import decimal # Transactional test class removing fixture at end class AutoTest(Test): @classmethod def tearDownClass(cls): for fixture in cls.fixtures: os.remove(fixture) super().tearDownClass() # Recover name from file name, ext = os.path.splitext(os.path.basename(fixture)) name = ''.join(x.capitalize() or '_' for x in name.split('_')) + 'TestCase' # Read the data with open(fixture, 'r') as file: data = json_decode(file.read()) # Creating a temporary fixture from templates models = data.pop('models', {}) with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', delete=False, suffix='.json') as temp_file: temp_file.write(json_encode(models)) temp_file.flush() # Created test class test_class = type(name, (AutoTest, ), dict(data=data, fixtures=[temp_file.name])) # Created test method tests = data.pop('tests') for index, test in enumerate(tests, start=1): def test_method(self, test=test): data = callback(test) with self.subTest(): for result in test.get('results', []): fields = result.get('fields', []) value = result.get('value', None) current = data for field in fields: current = current[field] # Explicit conversion to decimal if isinstance(current, decimal.Decimal): value = decimal.Decimal(str(value)) operator = OPERATORS.get(result.get('operator', '==')) operator(self, current, value) test_name = 'test_{}'.format( slugify(test.get('name', index)).replace('-', '_')) setattr(test_class, test_name, test_method) return test_class
def scripts(request): """ Scripts communs: """ context = {} for key, value in get_safe_settings().items(): try: json_encode(value) except TypeError: continue context[key] = value return { 'urls': json_encode(get_urls(request).data), 'user': json_encode(user_infos(request).data), 'context': json_encode(context), }
def as_sql(self, compiler, connection): if is_postgresql(connection): lhs, lhs_params = self.process_lhs(compiler, connection) rhs, rhs_params = self.process_rhs(compiler, connection) assert len(rhs_params) == 1, _("A dictionary must be provided as argument") value, *junk = rhs_params # assert isinstance(value, dict), _("Lookup argument must be a dictionary") return '%s %s %s::jsonb' % (lhs, self.lookup_operator, rhs), [json_encode(value)] raise NotImplementedError( _("The lookup '{lookup}' is only supported in PostgreSQL").format( lookup=self.lookup_name))
def __repr__(self): return json_encode(self, sort_keys=True)
def get_prep_value(self, value): if value is not None: return json_encode(value, cls=self.encoder, sort_keys=True) return value
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 exporter(self, file): """ Exporte les données de tarification dans un document Excel :param file: Chemin vers le document Excel :return: Rien """ workbook = Workbook() self.dropdowns = {} # Style des titres self.title_font = Font(bold=True) self.metadata = {} # Feuille d'aide sur les données worksheet = workbook.active worksheet.title = str(_("Informations")) titles = [_("modèle"), _("champ"), _("type"), _("description")] widths = {} for column, title in enumerate(titles, start=1): cell = worksheet.cell(row=1, column=column) cell.value = str(title) cell.font = self.title_font column_letter = get_column_letter(column) widths[column_letter] = len(str(cell.value)) + CELL_OFFSET row = 2 for model in self.models: meta = model._meta for field in meta.fields + meta.many_to_many: if field.auto_created or not (field.editable or self.non_editables): continue datas = [ meta.verbose_name.capitalize(), field.verbose_name, TYPES[field.get_internal_type()], field.help_text ] if field.choices: self.dropdowns[model, field.name] = [ str(value) for key, value in field.flatchoices ] for column, data in enumerate(datas, start=1): cell = worksheet.cell(row=row, column=column) cell.value = str(data) column_letter = get_column_letter(column) widths[column_letter] = max(widths[column_letter], len(str(data)) + CELL_OFFSET) row += 1 # Redimensionne les colonnes for column_letter, width in widths.items(): worksheet.column_dimensions[column_letter].width = width # Listes déroulantes worksheet = workbook.create_sheet(title=str(DROPDOWN_NAME)) worksheet.sheet_state = 'hidden' for row in zip_longest(*self.dropdowns.values(), fillvalue=None): worksheet.append(row) for index, key in enumerate(self.dropdowns.keys(), start=1): column = get_column_letter(index) self.dropdowns[key] = DataValidation(type='list', formula1='={}!${}:${}'.format( DROPDOWN_NAME, column, column)) # Feuille par modèle for model in self.models: self._write_model(workbook, model) # Export des métadatas worksheet = workbook.create_sheet(title=str(METADATA_NAME)) fields = [('code', 'Code'), ('cle', 'Clé'), ('valeur', 'Valeur')] 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 # On construit la feuille des métadonnées ligne par ligne en bouclant sur notre dictionnaire de métadonnées row = 2 for id, liste_tuple_meta in self.metadata.items(): for key, value in liste_tuple_meta: # La colonne 1 correspond au code cell = worksheet.cell(row=row, column=1) cell.value = id # La colonne 2 correspond à la clé cell = worksheet.cell(row=row, column=2) cell.value = key # La colonne 3 correspond à la valeur cell = worksheet.cell(row=row, column=3) try: cell.value = value except Exception: cell.value = json_encode(value) row += 1 workbook.save(file)
def prepare_value(self, value): if isinstance(value, JsonField.InvalidInput): return value return json_encode(value, sort_keys=True)
def from_native(self, data): return json_encode(data, sort_keys=True)