lunes, 11 de marzo de 2019

Django: Importar Registros desde Excel

#Import #Data #Django #Python 


En esta ocasión veremos cómo importar datos desde un archivo en excel.  Usaremos la librería django-import-export y como su nombre lo indica, es una librería para manejar la importación/exportación de datos.

Esta librería soporta muchos formatos, incluídos xls,csv, json, yaml y otros formatos soportados por tablib.  También tiene una integración con el admin de django.

Para tal caso, tomaremos el código fuente del curso de Desarrollo Web con Python usando Django, pero crearemos una nueva aplicación.


 manage.py startapp export  

Y de acá, asumimos que ya has agregado en el Settings.py.  Si tienes dudas, puedes ver en curso anteriomente mostrado haciendo click en este enlace.

Instalar Librería

 pip install django-import-export  

Y actualizamos el archivo de configuración agregándole la nueva librería

 'import_export',  

Adicionalmente, debemos agregar una configuración que permita que la importación se haga usando transacciones de la base de datos.

 IMPORT_EXPORT_USE_TRANSACTIONS = True  

Recursos

La librería django-import-export trabaja con el concepto de Recurso, el cual es definición de clases muy similiar a como Django maneja los modelos de formularios y las clases admin.

Crearemos un modelo, el cual será donde se suba toda la información importada del archivo excel.

 #models.py  
 from django.db import models  
 class Persona(models.Model):  
   nombre = models.CharField(max_length=30)  
   email = models.EmailField(blank=True)  
   fecha_nac = models.DateField()  
   ciudad = models.CharField(max_length=100, blank=True)  

Se creará un archivo resource.py donde estará toda la lógica de la librería.
 #resources.py  
 from import_export import resources  
 from .models import Persona  
 class PersonaResource(resources.ModelResource):  
   class Meta:  
     model = Persona  

Esta es la definición más sencilla.  Puedes pasarle diferentes configuraciones a la clase Meta,
como fields, exclude, etc.  Puedes ver la documentación para más detalles

Importando Datos


Tomemos como ejemplo, el archivo xls siguiente


El Id debe estar presente porque es su llave primaria.  Como será generado, no es necesario que se especifique.

Ahora crearemos la plantilla, le pondremos por nombre export/importar.html.

 {% extends 'base/base.html' %}  
 {% block contenido %}  
  <form method="post" enctype="multipart/form-data">  
   {% csrf_token %}  
   <input type="file" name="xlsfile">  
   <button type="submit">Subir</button>  
  </form>  
 {% endblock %}  

Vista

from tablib import Dataset 
 
 def importar(request):  
   #template = loader.get_template('export/importar.html')  
   if request.method == 'POST':  
     persona_resource = PersonaResource()  
     dataset = Dataset()  
     #print(dataset)  
     nuevas_personas = request.FILES['xlsfile']  
     #print(nuevas_personas)  
     imported_data = dataset.load(nuevas_personas.read())  
     #print(dataset)  
     result = persona_resource.import_data(dataset, dry_run=True) # Test the data import  
     #print(result.has_errors())  
     if not result.has_errors():  
       persona_resource.import_data(dataset, dry_run=False) # Actually import now  
   return render(request, 'export/importar.html')  

He dejado comentado algunos prints, que te serían muy interesante ver qué va pasando por ahí.

Probando

Debemos hacer las migraciones necesarias para que se cree el modelo en la base de datos y aplicarla.  Luego de eso, debemos levantar el servidor.  Y accedemos, sabemos que todo va bien si el log está "limpio" y la aplicación se carga en el login.


Creé una ruta (en el archivo urls.py de la app), /export/import

from django.urls import path

from .views import importar

urlpatterns = [
path('import', importar , name='import'),
]

Luego de las credenciales (que no sería necesario especificarla), accedo a la ruta  http://127.0.0.1:8000/export/import.



Ahí cargo el archivo excel.


Y al presionar el botón subir, todo sucederá bastante rápido, ahí voy a revisar la tabla y esto es lo que encuentro.


Sólo teniendo cuidado que las fechas no las formatee Excel, en mi caso yo les antepuse una comilla simple para que siguiera en formato de texto.

Si te ha sido de utilidad este tutorial, te pediría lo compartas con tus amigos, conocidos y farmiliares.

Si estás interesado en aprender más, puedes inscribirte en el curso de Desarrollo Web con Python usando Django o ver alguno de los cursos para crecer como experto en desarrollo web con django viendo el siguiente enlace.

Bueno, será para la próxima.

5 comentarios:

  1. ¿Cuando se está actualizando los registros de un modelo el cual ya tiene información previa, el archivo de excel solo debe tener los registros a actualizar?

    ResponderBorrar
  2. ¿como importas el objetoResource desde la vista?

    ResponderBorrar
    Respuestas
    1. No se si ya lo solucionaste o encontraste otra solucion, pero yo lo hice asi : from nombre.resources import ArticulosResource
      Saludos

      Borrar
  3. Estoy tratando de importar un reporte de SAP a una base de datos Postgres, voy a probar tu método, la única restricción que tiene mi app es que necesito por temas de seguimiento que se agregue la fecha de creación de cada registro de tal manera que un conjunto de datos de un solo archivo tengan la misma fecha ya que la tabla irá creciendo gradualmente.

    ResponderBorrar
    Respuestas
    1. fue más fácil utilizando la integración de django-import-export desde admin. Ya que en tiempo de ejecución al subir el xlsx retorna None cuando se carga info. No funciona tu método!

      Borrar

¿Tienes algún comentario? ¿Qué te ha parecido este artículo? Cuéntalo.

 
>