Compare commits
14 Commits
70460b3310
...
dev/no_doc
| Author | SHA1 | Date | |
|---|---|---|---|
| f1c3f711c4 | |||
| ce89e67181 | |||
| ab5c0e6d54 | |||
|
|
4ff8888472 | ||
|
|
0ff577e8b1 | ||
| 96eb619a95 | |||
| ccaaca4b4e | |||
| ff4dcd2834 | |||
| 423a904d7e | |||
|
|
69dc786cac | ||
|
|
8f64d2abdb | ||
|
|
3817618208 | ||
|
|
f867cac9c1 | ||
|
|
79debe5f46 |
91
README.md
91
README.md
@@ -1,89 +1,6 @@
|
|||||||
# exportPDF
|
# exportPDF dev/no_docker
|
||||||
|
> **Precaución:**
|
||||||
|
> Para instalar en modo producción, utlize la rama main
|
||||||
|
|
||||||
Funcionalidad para implementar la capacidad de exportar los datos de un recurso a formato PDF.
|
Funcionalidad para implementar la capacidad de exportar los datos de un recurso a formato PDF.
|
||||||
Los modelos de recursos habilitados para la función son los siguientes:
|
esta rama es para el caso de un entorno de desarrollo clásico, es decir sin utilizar contenedores
|
||||||
|
|
||||||
* Patrimonio material - Bienes inmuebles
|
|
||||||
* Patrimonio material - Bienes muebles
|
|
||||||
* Patrimonio inmaterial
|
|
||||||
* Organización o persona
|
|
||||||
|
|
||||||
# Para agregar la funcionalidad ExportPDF a un proyecto de Arches puede seguir el siguiente procedimiento.
|
|
||||||
Procedimiento válido para un proyecto en modo desarrollo implementado con un enfoque tradicional sin contenedores.
|
|
||||||
Para el caso de un enfoque utilizando contenedores o en modo Producción, el proceso varía levemente.
|
|
||||||
|
|
||||||
### 0. Instalar dependencias y librerias de python (servidor Ubuntu)
|
|
||||||
Solo en caso de que su proyecto de arches resida en una implementación según la guía oficial de archesproject
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo apt install build-essential python3.12-dev python3.12-pip python3.12-setuptools python3.12-wheel python3.12-cffi
|
|
||||||
sudo apt install build-essential python3-dev python3-pip python3-setuptools python3-wheel python3-cffi libcairo2 libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info
|
|
||||||
```
|
|
||||||
y en el entorno de (arches) python:
|
|
||||||
|
|
||||||
```python
|
|
||||||
pip install django-weasyprint
|
|
||||||
pip install pypdf
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1. Clonar este repositorio en alguna carpeta de su servidor.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# puede ser en el home del servidor
|
|
||||||
git clone https://gitea.patrimonio.org.bo/sysadmin/sprpcb-exportpdf-func.git
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Copiar los archivos necesarios para crear una nueva plantilla de reporte que contendrá los botones necesarios:
|
|
||||||
```shell
|
|
||||||
cp -r ../sprpcb-exportpdf-func/reportes ./mi_proyecto/reportes
|
|
||||||
cp ../sprpcb-exportpdf-func/templates_views_report-templates/export-pdf-report.htm ./mi_proyecto/templates/views/report-templates/
|
|
||||||
cp ../sprpcb-exportpdf-func/media_js_reports/export-pdf-report.js ./mi_proyecto/media/js/reports/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Registrar la plantilla personalizada de proyecto que agrega los botones necesarios:
|
|
||||||
```python
|
|
||||||
python manage.py report register -s mi_proyecto/reportes/export-pdf-report.json
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Agregar la vista personalizada creando (copiando) las carpetas indicadas y luego los contenidos respectivos:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# en caso de que el repo clonado esté en el home y desde la 1er carpeta mi_proyecto
|
|
||||||
cp -r ../sprpcb-exportpdf-func/pdf ./mi_proyecto/pdf
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Copiar las plantillas pdf correspondientes a los modelos de recursos:
|
|
||||||
```shell
|
|
||||||
cp -r ../sprpcb-exportpdf-func/templates_reports ./mi_proyecto/templates/reports
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Agregar una fuente y una entrada de ruta en el archivo urls.py como valor de urlpatterns:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
from .pdf.views import export_resource_pdf
|
|
||||||
#urlpatterns = [
|
|
||||||
# ...
|
|
||||||
path('export/pdf/<str:resourceid>/<str:printubic>/<str:printimgs>/<str:printpdfs>/', export_resource_pdf, name='export_resource_pdf'),
|
|
||||||
# project-level urls
|
|
||||||
#]
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. A continuación, asegúrese de reconstruir la interfaz de su proyecto para habilitar los cambios:
|
|
||||||
|
|
||||||
```
|
|
||||||
npm run build_development
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8. Configuración final
|
|
||||||
Por último, se deben modificar los modelos de recursos para que adopten la nueva plantilla de reporte registrada:
|
|
||||||
|
|
||||||
Cuando haya terminado, debería ver los botones de exportar en la ventana de vista de reporte de su modelo de recursos:
|
|
||||||

|
|
||||||
|
|
||||||
### 9. Forma de uso:
|
|
||||||
|
|
||||||
El botón "Exportar a PDF", de manera predeterminada, crea el reporte PDF incluyendo casi todos los datos del recurso. Y de manera opcional se pueden incluir 3 características adicionales a través de los botones adyacentes que controlan los siguientes parámetros:
|
|
||||||
* Incluir ubicación detallada: Se puede incluir datos de ubicación (geo-localización) que podrían estar contraindicados en algunos tipos de recursos.
|
|
||||||
* Incluir imágenes adjuntas: Una galería de imágenes distribuida en mosaicos de 2x6 imágenes por hoja a manera de Anexo al informe (existen recursos que tienen más de 20 imágenes relacionadas)
|
|
||||||
* Incluir documentos (pdf) adjuntos: se ajuntan los documentos relacionados en el mismo archivo pdf del informe
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
26
copy2proyfolder.sh
Executable file
26
copy2proyfolder.sh
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!bin/bash
|
||||||
|
|
||||||
|
#Script demostrativo para copiar del repo clonado a las carpetas de proyecto
|
||||||
|
#Utilize con precaución
|
||||||
|
|
||||||
|
echo -e "\n\t Script para copiar a carpeta de proyecto"
|
||||||
|
read -p "Escribe la carpeta de proyecto ( ejem: ~/mi_proy/miproy ): " destino
|
||||||
|
|
||||||
|
echo $destino
|
||||||
|
if [ ! -d "$destino" ]; then
|
||||||
|
echo "La carpeta de destino no existe. Intente nuevamente!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p $destino/pdf
|
||||||
|
cp ./pdf/views.py $destino/pdf/
|
||||||
|
|
||||||
|
cp ./media_js_reports/export-pdf-report.js $destino/media/js/reports/
|
||||||
|
|
||||||
|
cp -r ./reportes $destino/
|
||||||
|
|
||||||
|
mkdir -p $destino/templates/views/report-templates
|
||||||
|
cp ./templates_views_report-templates/export-pdf-report.htm $destino/templates/views/report-templates/
|
||||||
|
|
||||||
|
mkdir -p $destino/templates/reports
|
||||||
|
cp ./templates_reports/* $destino/templates/reports/
|
||||||
31
pdf/views.py
31
pdf/views.py
@@ -1,10 +1,11 @@
|
|||||||
# mi_proyecto/pdf/views.py
|
# mi_proyecto/pdf/views.py
|
||||||
# dpsk - 2026
|
|
||||||
import io
|
import io
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from weasyprint import HTML
|
from weasyprint import HTML
|
||||||
|
from arches.app.models.models import GraphModel
|
||||||
from arches.app.models.resource import Resource
|
from arches.app.models.resource import Resource
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -19,9 +20,14 @@ import json
|
|||||||
import ast
|
import ast
|
||||||
|
|
||||||
def static_map_view(geojson_colec, sat_map):
|
def static_map_view(geojson_colec, sat_map):
|
||||||
|
g_sys_cfg=GraphModel.objects.get(name='{"en": "Arches System Settings"}')
|
||||||
|
r_sys_cfg=Resource.objects.get(graph=g_sys_cfg)
|
||||||
|
r_sys_cfg_data=r_sys_cfg.to_json()
|
||||||
|
access_token = r_sys_cfg_data['Map Settings']['Mapbox']['MAPBOX_API_KEY']
|
||||||
|
|
||||||
geojson_dict = ast.literal_eval(geojson_colec)
|
geojson_dict = ast.literal_eval(geojson_colec)
|
||||||
if sat_map:
|
if sat_map:
|
||||||
|
style_id = "satellite-streets-v12" # streets-v12 | outdoors-v11 | satellite-streets-v12
|
||||||
for geo in geojson_dict['features'] :
|
for geo in geojson_dict['features'] :
|
||||||
if geo['geometry'].get('type') == 'Polygon':
|
if geo['geometry'].get('type') == 'Polygon':
|
||||||
geo['properties'] = {
|
geo['properties'] = {
|
||||||
@@ -42,25 +48,20 @@ def static_map_view(geojson_colec, sat_map):
|
|||||||
"stroke-width": 2,
|
"stroke-width": 2,
|
||||||
"stroke-opacity": 0.8
|
"stroke-opacity": 0.8
|
||||||
}
|
}
|
||||||
|
else:
|
||||||
|
style_id = "light-v11"
|
||||||
|
|
||||||
geojson_string = json.dumps(geojson_dict, separators=(',', ':'))
|
geojson_string = json.dumps(geojson_dict, separators=(',', ':'))
|
||||||
encoded_geojson = urllib.parse.quote(geojson_string)
|
encoded_geojson = urllib.parse.quote(geojson_string)
|
||||||
|
|
||||||
username = "mapbox"
|
username = "mapbox"
|
||||||
if sat_map:
|
width, height = 400, 400
|
||||||
style_id = "satellite-streets-v12" # streets-v12 | outdoors-v11 | satellite-streets-v12
|
padding = 100
|
||||||
else:
|
|
||||||
style_id = "light-v11"
|
|
||||||
|
|
||||||
width, height = 340, 340
|
|
||||||
|
|
||||||
# Procedimiento pendiente para extraer el token desde la configuración del sistema
|
|
||||||
access_token = 'pk.eyJ1IjoianNidXJnb3N2IiwiYSI6ImNsaWhoN3ZtMTBxeHUzZm1xaGM0cGpxOXIifQ.ki3vldVB5MwZMqDSpLSjLg'
|
|
||||||
|
|
||||||
mapbox_url = (
|
mapbox_url = (
|
||||||
f"https://api.mapbox.com/styles/v1/{username}/{style_id}/static/"
|
f"https://api.mapbox.com/styles/v1/{username}/{style_id}/static/"
|
||||||
f"geojson({encoded_geojson})/auto/{width}x{height}"
|
f"geojson({encoded_geojson})/auto/{width}x{height}"
|
||||||
f"?access_token={access_token}"
|
f"?padding={padding}&access_token={access_token}"
|
||||||
)
|
)
|
||||||
|
|
||||||
response = requests.get(mapbox_url)
|
response = requests.get(mapbox_url)
|
||||||
@@ -216,7 +217,9 @@ def export_resource_pdf(request, resourceid, printubic, satmap, printimgs, print
|
|||||||
if ruta_medios is not None and bool(int(printpdfs)) :
|
if ruta_medios is not None and bool(int(printpdfs)) :
|
||||||
for medio in reduce(getitem, ruta_medios[:-1], resource_data)[ruta_medios[-1]] :
|
for medio in reduce(getitem, ruta_medios[:-1], resource_data)[ruta_medios[-1]] :
|
||||||
if medio['formato'] == 'application/pdf' :
|
if medio['formato'] == 'application/pdf' :
|
||||||
merger.append(PdfReader(f'{root_path}/uploadedfiles/{medio["file"]}'))
|
medio_file = f'{root_path}/uploadedfiles/{medio["file"]}'
|
||||||
|
with open(medio_file,'rb') as pdf_file :
|
||||||
|
merger.append(pdf_file)
|
||||||
output_buffer = io.BytesIO()
|
output_buffer = io.BytesIO()
|
||||||
merger.write(output_buffer)
|
merger.write(output_buffer)
|
||||||
merger.close()
|
merger.close()
|
||||||
@@ -224,7 +227,7 @@ def export_resource_pdf(request, resourceid, printubic, satmap, printimgs, print
|
|||||||
output_buffer = io.BytesIO()
|
output_buffer = io.BytesIO()
|
||||||
merger.write(output_buffer)
|
merger.write(output_buffer)
|
||||||
merger.close()
|
merger.close()
|
||||||
|
output_buffer.seek(0)
|
||||||
response = HttpResponse(output_buffer.getvalue(), content_type='application/pdf')
|
response = HttpResponse(output_buffer.read(), content_type='application/pdf')
|
||||||
response['Content-Disposition'] = f'attachment; filename="{nombre_pdf}.pdf"'
|
response['Content-Disposition'] = f'attachment; filename="{nombre_pdf}.pdf"'
|
||||||
return response
|
return response
|
||||||
Reference in New Issue
Block a user