From dce8a4e0953a36fc2d7f6f62ba43c564eec7f3e6 Mon Sep 17 00:00:00 2001 From: AdalbertoCV <34152734@uaz.edu.mx> Date: Fri, 11 Oct 2024 12:35:45 -0600 Subject: [PATCH] =?UTF-8?q?Exclusion=20de=20columnas=20no=20necesarias=20e?= =?UTF-8?q?n=20tablas=20din=C3=A1micas,=20columna=20nombre=20en=20reportes?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cosiap_api/dynamic_tables/DynamicTable.py | 125 +++++++++--------- .../migrations/0002_reporte__nombre.py | 19 +++ cosiap_api/dynamic_tables/models.py | 3 +- cosiap_api/dynamic_tables/views.py | 81 +++++------- 4 files changed, 118 insertions(+), 110 deletions(-) create mode 100644 cosiap_api/dynamic_tables/migrations/0002_reporte__nombre.py diff --git a/cosiap_api/dynamic_tables/DynamicTable.py b/cosiap_api/dynamic_tables/DynamicTable.py index 07e428c..771b204 100644 --- a/cosiap_api/dynamic_tables/DynamicTable.py +++ b/cosiap_api/dynamic_tables/DynamicTable.py @@ -24,7 +24,64 @@ from zipfile import ZipFile import io from dynamic_forms.models import RDocumento -exclude_pattern = re.compile(r'^password$|^last_login$|^created_at$|^updated_at$|^usuario_ptr$|^groups$|^user_permissions$|^dynamic_form__nombre$|^dynamic_form__secciones$', re.IGNORECASE) +exclude_pattern = re.compile(r'id|imagen|staff|user|active|timestamp|^password$|^last_login$|^created_at$|^updated_at$|^usuario_ptr$|^groups$|^user_permissions$|^dynamic_form__nombre$|^dynamic_form__secciones$',re.IGNORECASE) + + +class Reporte(serializers.ModelSerializer): + ''' + Clase para crear, actualziar y serialziar reportes de tabla dinámica. + ''' + + class Meta: + model = DynamicTableReport + fields = '__all__' + + + def create(self, validated_data): + ''' + Método que se encargará de guardar en la base de datos una nueva configuración para la tabla dinámica + + parámetros: + - validated_data: Datos validados según la configuración de la base de datos + ''' + + # Verificamos si ya existe una configuración igual en la base de datos + instance = DynamicTableReport.objects.filter( + nombre = validated_data['nombre'], + model_name=validated_data['model_name'], + columns=validated_data['columns'], + exclude_columns=validated_data.get('exclude_columns', None), + search_query=validated_data.get('search_query', None), + filters=validated_data.get('filters', None) + ).first() + + if instance: + # Si ya existe una configuración igual, la retornamos + return instance + + # Si no existe, creamos una nueva instancia + instance = DynamicTableReport.objects.create(**validated_data) + return instance + + def update(self, instance, validated_data): + ''' + Método para modificar una configuración de reporte. + + param instance: Instancia de DynamicTableReport + param validated_data: Nuevos datos + ''' + instance.nombre = validated_data.get('nombre', instance.nombre) + instance.model_name = validated_data.get('model_name', instance.model_name) + instance.columns = validated_data.get('columns', instance.columns) + instance.exclude_columns = validated_data.get('exclude_columns', instance.exclude_columns) + instance.search_query = validated_data.get('search_query', instance.search_query) + instance.filters = validated_data.get('filters', instance.filters) + instance.exclude_filters = validated_data.get('exclude_filters', instance.exclude_filters) + + instance.save() + return instance + + class DynamicTable(serializers.ModelSerializer): ''' @@ -41,20 +98,6 @@ class DynamicTable(serializers.ModelSerializer): if model_class is None: raise ValueError("El argumento 'model_class' es obligatorio.") self.model_class = model_class - - - def to_representation(self, instance): - ''' - Método to_representation: Devuelve la representación de la configuración de tabla dinámica excluyendo la data - - param: instance: instancia de configuración de tabla dinámica - ''' - representation = super().to_representation(instance) - # Eliminar el campo 'data' - representation.pop('data', None) - # No retornamos el modelo name - representation.pop('model_name', None) - return representation def get_data(self, obj): @@ -296,14 +339,14 @@ class DynamicTable(serializers.ModelSerializer): for field in model._meta.get_fields(): # Verificar si el campo debe ser excluido - if exclude_pattern.fullmatch(field.name): + if exclude_pattern.search(field.name) and field.name != "id" and "modalidad" not in field.name.lower(): continue if isinstance(field, ForeignKey): related_model = field.related_model related_fields = DynamicTable.get_model_fields(related_model, visited_models) for related_field_name, related_field_verbose_name in related_fields.items(): - if not exclude_pattern.fullmatch(related_field_name): + if not exclude_pattern.search(related_field_name): fields[f"{field.name}__{related_field_name}"] = f"{related_field_verbose_name}" elif isinstance(field, ManyToManyField): fields[field.name] = field.verbose_name @@ -385,7 +428,7 @@ class DynamicTable(serializers.ModelSerializer): """ for field in instance._meta.get_fields(): - if exclude_pattern.fullmatch(field.name) or isinstance(field, ManyToOneRel): + if (exclude_pattern.search(field.name) and field.name != "id" and "modalidad" not in field.name.lower()) or isinstance(field, ManyToOneRel): continue try: field_value = getattr(instance, field.name, None) @@ -411,52 +454,6 @@ class DynamicTable(serializers.ModelSerializer): data[field.name] = str(e) - - def create(self, validated_data): - ''' - Método que se encargará de guardar en la base de datos una nueva configuración para la tabla dinámica - - parámetros: - - validated_data: Datos validados según la configuración de la base de datos - ''' - - # Verificamos si ya existe una configuración igual en la base de datos - instance = DynamicTableReport.objects.filter( - model_name=validated_data['model_name'], - columns=validated_data['columns'], - exclude_columns=validated_data.get('exclude_columns', None), - search_query=validated_data.get('search_query', None), - filters=validated_data.get('filters', None) - ).first() - - if instance: - # Si ya existe una configuración igual, la retornamos - return instance - - # Si no existe, creamos una nueva instancia - instance = DynamicTableReport.objects.create(**validated_data) - return instance - - - def update(self, instance, validated_data): - ''' - Método para modificar una configuración de reporte. - - param instance: Instancia de DynamicTableReport - param validated_data: Nuevos datos - ''' - instance.model_name = validated_data.get('model_name', instance.model_name) - instance.columns = validated_data.get('columns', instance.columns) - instance.exclude_columns = validated_data.get('exclude_columns', instance.exclude_columns) - instance.search_query = validated_data.get('search_query', instance.search_query) - instance.filters = validated_data.get('filters', instance.filters) - instance.exclude_filters = validated_data.get('exclude_filters', instance.exclude_filters) - - instance.save() - return instance - - - def get_field(self, instance, field_name): """ Obtiene el campo del modelo para el campo especificado, ya sea en el modelo principal o en un modelo relacionado. diff --git a/cosiap_api/dynamic_tables/migrations/0002_reporte__nombre.py b/cosiap_api/dynamic_tables/migrations/0002_reporte__nombre.py new file mode 100644 index 0000000..2d90d9a --- /dev/null +++ b/cosiap_api/dynamic_tables/migrations/0002_reporte__nombre.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0.8 on 2024-10-11 17:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dynamic_tables', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='dynamictablereport', + name='nombre', + field=models.CharField(default='Reporte', max_length=255), + preserve_default=False, + ), + ] diff --git a/cosiap_api/dynamic_tables/models.py b/cosiap_api/dynamic_tables/models.py index 899b59b..154067b 100644 --- a/cosiap_api/dynamic_tables/models.py +++ b/cosiap_api/dynamic_tables/models.py @@ -10,6 +10,7 @@ class DynamicTableReport(models.Model): - search_query (Cadena de búsqueda para la obtención de los datos del modelo y sus relaciones) - filters (Filtros a aplicar recibidos desde el front) ''' + nombre = models.CharField(max_length=255) model_name = models.CharField(max_length=100) columns = models.JSONField() # Campos opcionales @@ -19,7 +20,7 @@ class DynamicTableReport(models.Model): exclude_filters = models.JSONField(blank=True, null=True) def __str__(self): - return 'Tabla Dinámica: ' + self.model_name + return self.nombre diff --git a/cosiap_api/dynamic_tables/views.py b/cosiap_api/dynamic_tables/views.py index da67c20..9755cf3 100644 --- a/cosiap_api/dynamic_tables/views.py +++ b/cosiap_api/dynamic_tables/views.py @@ -1,7 +1,7 @@ from django.shortcuts import render, get_object_or_404 from rest_framework.response import Response from rest_framework import status -from dynamic_tables.DynamicTable import DynamicTable +from dynamic_tables.DynamicTable import DynamicTable, Reporte from dynamic_tables.DynamicTableDynamicForm import DynamicTableDynamicForm from rest_framework.permissions import AllowAny, IsAuthenticated from dynamic_tables.models import DynamicTableReport @@ -61,46 +61,37 @@ class DynamicTableAPIView(BasePermissionAPIView): ''' Crear una configuración con los datos actuales de la request, sobrescribiendo los predeterminados si se proporcionan. ''' - if request.method == 'GET': - # Extraemos el parámetro 'reporte' desde los parámetros de consulta - reporte_data = request.query_params.get('reporte', '{}') - try: - # Convertimos el string JSON en un diccionario - reporte_data = json.loads(reporte_data) - except ValueError: - reporte_data = {} - - elif request.method == 'PUT': - # Extraemos el parámetro 'reporte' desde los datos del cuerpo de la solicitud PUT - reporte_data = request.data.get('reporte', {}) - if isinstance(reporte_data, str): - try: - reporte_data = json.loads(reporte_data) - except ValueError: - reporte_data = {} - else: - reporte_data = {} - - # Verificamos si reporte_data es un diccionario vacío o None, asignamos configuración predeterminada - if not reporte_data: - reporte_data = { - #'model_name': self.model_name, - 'columns': self.columns, - 'filters': self.filters, - 'exclude_columns': self.exclude_columns, - 'search_query': self.search_query, - 'exclude_filters': self.exclude_filters - } - - # debemos actualizar las variables predeterminadas para el futuro uso de las mismas - #self.model_name = reporte_data.get("model_name", self.model_name) - self.columns = reporte_data.get("columns", self.columns) - self.filters = reporte_data.get("filters", self.filters) - self.exclude_columns = reporte_data.get("exclude_columns", self.exclude_columns) - self.search_query = reporte_data.get("search_query", self.search_query) - self.exclude_filters = reporte_data.get("exclude_filters", self.exclude_filters) - reporte_data["model_name"] = self.model_name - return DynamicTableReport(**reporte_data) + try: + reporte_id = request.query_params.get('reporte_id', None) + if reporte_id: + reporte_data = DynamicTableReport.objects.get(id=reporte_id) + self.model_name = reporte_data.model_name + self.columns = reporte_data.columns + self.filters = reporte_data.filters + self.exclude_columns = reporte_data.exclude_columns + self.search_query = reporte_data.search_query + self.exclude_filters = reporte_data.exclude_filters + return reporte_data + else: + reporte_data = { + #'model_name': self.model_name, + 'columns': self.columns, + 'filters': self.filters, + 'exclude_columns': self.exclude_columns, + 'search_query': self.search_query, + 'exclude_filters': self.exclude_filters + } + self.columns = reporte_data.get("columns", self.columns) + self.filters = reporte_data.get("filters", self.filters) + self.exclude_columns = reporte_data.get("exclude_columns", self.exclude_columns) + self.search_query = reporte_data.get("search_query", self.search_query) + self.exclude_filters = reporte_data.get("exclude_filters", self.exclude_filters) + reporte_data["model_name"] = self.model_name + return DynamicTableReport(**reporte_data) + except Exception as e: + data = {} + Mensaje.error(data, str(e)) + return Response(data, status = status.HTTP_400_BAD_REQUEST) def get(self, request, pk=None): @@ -258,11 +249,11 @@ class ReporteAPIView(BasePermissionAPIView): ''' if 'pk' in kwargs: instance = get_object_or_404(DynamicTableReport, pk=kwargs['pk']) - serializer = DynamicTable(instance) + serializer = Reporte(instance) return Response(serializer.data) queryset = DynamicTableReport.objects.all() - serializer = DynamicTable(queryset, many=True) + serializer =Reporte(queryset, many=True) return Response(serializer.data) def post(self, request, *args, **kwargs): @@ -270,7 +261,7 @@ class ReporteAPIView(BasePermissionAPIView): Método POST para crear una nueva configuración de reporte ''' response_data = {} - serializer = DynamicTable(data=request.data) + serializer = Reporte(data=request.data) if serializer.is_valid(): configuracion_reporte = serializer.save() Mensaje.success(response_data, 'Reporte creado con exito.') @@ -287,7 +278,7 @@ class ReporteAPIView(BasePermissionAPIView): response_data = {} configuracion = get_object_or_404(DynamicTableReport, pk= pk) - serializer = DynamicTable(instance=configuracion, data=request.data) + serializer = Reporte(instance=configuracion, data=request.data) if serializer.is_valid(): # guardamos los cambios serializer.save() -- GitLab