Django HTML to PDF with links and dynamic data - python

I have Django 1.7.1 and Python 2.7.8
I want to get a PDF from a rendered html template, I have tried PISA (xhtml2pdf) but first, i had a lot of problems with Bootstrap css, then, after deleting some lines, this message appeared:
'CSSTerminalFunction' object has no attribute 'lower'
'lower' seems to be part of python 3 and not available in 2.7 (If I am wrong, please tell me)
Now I am trying to use wkhtmltopdf but the documentation is too basic. It describes only one simple example with static HTML
Can someone explain how I can get a PDF with my actual template?
In the template, i have 2 links to css files, and one Image (logo)
I have some bootstrap css style, and i want to use it if possible
I put a "queryset" (actually a tuple) in the template to be rendered inside a table
I also put some string parameters to be rendered in deferent locations in my html.
Here is a part of the template
{% extends 'reporteBase.html' %}
{% block titulo %}Reporte - Inventario por UbicaciĆ³n{% endblock %}
{% block content %}
{% if productos %}
<h2>Inventario de la ubicaciĆ³n "{{ ubi }}"</h2>
<div class="row" style="margin-top: 2em">
<table class="table table-condensed" data-resizable-columns-id="demo-table">
<thead>
<tr>
<th data-resizable-column-id="mod">Modelo/Item</th>
<th data-resizable-column-id="desc">Descripcion</th>
<th data-resizable-column-id="cant" data-noresize>Cantidad</th>
<th data-resizable-column-id="unidad" data-noresize>Unidad</th>
<th data-resizable-column-id="ubi" data-noresize>Ubicacion</th>
</tr>
</thead>
<tbody>
{% for p in productos %}
<tr>
<td>{{ p.producto__item}}</td>
<td>{{ p.producto__descripcion }}</td>
<td>{{ p.sum_cantidad }}</td>
<td>{{ p.producto__unidad }}</td>
<td>{{ p.ubicacion__nombre }}</td>
</tr>
{% empty %}
<tr><td colspan=4>No hay Productos</td></tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{% endblock %}
Thanks!

A view needs to render the template as a PDF. That's what the code from the django-wkhtmltopdf Simple Example does.
Try rendering the page as HTML first to make sure the template is working. You could do this with a view like:
url(r'^html_preview/$',
TemplateView.as_view(template_name='pdf_template.html'))
After you've solved any issues with the template, then try it with PDFTemplateView.

Related

Flask redirect to url_for

I have he following data_analytics.html` which in the end provides the
view:
{% extends 'base.html' %} {% block title %}Home{% endblock %}
{% block content %}
<!-- <h1 align="center" >Your Files</h1> -->
<br />
<table class="table table-bordered table-hover">
<caption> Files Uploaded</caption>
<tr>
<th class="table-light"> # </th>
<th class="table-light">File Name</th>
<th class="table-light">Date</th>
<th class="table-light">Access Data</th>
</tr>
{% for file in csv_file %}
<tr>
<!-- <td>{{ file.id }}</td> -->
<th scope="row">1</th>
<td>{{ file.data }}</td>
<td>{{ file.date }}</td>
<td>View Data</td>
{%endfor%}
</table>
{% endblock %}
Is there a way that when the user clicks on the link to have displayed the content of the .csv file using python/flask ?
Tried to create a function that redirects to an url_for but not working`
try this:
In this 'a' put a 'target="_blank"'
View Data
And, in the python let's create a new function:
from flask import send_from_directory
#app.route('/csv')
def see_file():
return send_from_directory(directory='static', path='files/cheat_sheet.pdf')
Just change the path and the directory. And the file is going to open in a new tab.

Flask handle button click

I am trying to do a website to read CSV file and be able to view the data, edit, delete or add new rows/columns. I am able to read the data from a file and view it. I upload a CSV file using a form and then read the data and view it in a page. An example of data looks like this:
Here is the html code for the picture above:
{% extends 'base.html' %}
{% block title %}
Home page
{% endblock %}
{% block content %}
<table class="table">
<tr class="table__header">
<th class="table__cell"> Row </th>
{% for header in data[0] %}
<th class="table__cell"> {{ header }} </th>
{% endfor %}
</tr>
{% for row in data[1:] %}
<tr class="table__row">
<td>{{loop.index}}</td>
{% for cell in row %}
<td class="table__cell"> {{ cell }}</td>
{% endfor %}
<td width="130">
Edit
Delete
</td>
</tr>
{% endfor %}
</table>
{% endblock %}
As you can see I created two buttons, an edit and a delete button for each of the rows. I just do not know how to handle the click for the buttons. If for example I click edit then I want to get redirected to a new page where I can edit the particular row I choose to edit. If instead I click on delete then it will just delete the element. How can I handle the buttons? Can I only handle buttons via forms? or is there other ways? I am very new to Flask (have just programmed in it for 3-4 days) so I have no clue how to do. I tried to search for an awnser but I do not quite understand and I do not get anything similar to my project. Please help.

non repeating th for each table row

is there a way to remove the repeated th for each row?
I only want it to show at the top of the table, and not repeat for each row that I import from psql. I've searched and tried several options, but none seem to work for me. I'm using Flask and SQLAlchemy to connect to a postgre table. (the table is called injection)
This is part of my code:
{% block contents %}
<h1>Injection Data</h1>
{% for inject in injection %}
<table>
<tr>
<th>Timestamp</th>
<th>Cage Identifier</th>
<th>Ear Notch Number</th>
<th>Age</th>
<th>Date of Birth</th>
<th>Strain</th>
</tr>
<tr>
<td>{{inject.Timestamp}}</td>
<td>{{inject.Cage_Identifier}}</td>
<td>{{inject.Ear_Notch_Number}}</td>
<td>{{inject.Age}}</td>
<td>{{inject.DOB}}</td>
<td>{{inject.Strain}}</td>
</tr>
</table>
{% endfor %}
{% endblock contents %}
However, the column headers th will repeat for each row of data that is imported from the postgre table.
Your <th> and <table> must not be in loop only <tr><td></td></tr> needs to be in loop,
like below.
{% block contents %}
<h1>Injection Data</h1>
<table>
<tr>
<th>Timestamp</th>
<th>Cage Identifier</th>
<th>Ear Notch Number</th>
<th>Age</th>
<th>Date of Birth</th>
<th>Strain</th>
</tr>
{% for inject in injection %}
<tr>
<td>{{inject.Timestamp}}</td>
<td>{{inject.Cage_Identifier}}</td>
<td>{{inject.Ear_Notch_Number}}</td>
<td>{{inject.Age}}</td>
<td>{{inject.DOB}}</td>
<td>{{inject.Strain}}</td>
</tr>
{% endfor %}
</table>
{% endblock contents %}

Building a Bootstrap table with dynamic elements in Flask

I'm working with Flask on building a Bootstrap table out of a list of people taken from a SQLAlchemy database. However, the information I want to put in the table is appearing above it.
Here's the code in question:
<!DOCTYPE html>
{% extends "base.html" %}
{% block page_content %}
<div class="page-header">
<h1>componentes familiares</h1>
<table class="table">
<thead>
<th>name</th>
<th>age</th>
<th>option</th>
</thead>
<tbody>
{% for person in people %}
<tr>{{ person.name }}</tr>
<tr>{{ person.age }}</tr>
<tr>{{ person.option }}</tr>
{% endblock %}
</tbody>
</table>
{% endblock %}
(This is already a slimmed-down version, since I kept taking stuff off to see if it would solve the problem.)
But let's say I have two persons in my database, Alice, and Bob. Alice is 30 and Bob is 40, Alice's option is 1 and Bob's is 2. This is what I get:
The information is there, but it's rendered above the table. And right below it comes the table header and an empty table row.
Links
I found another question about Bootstrap tables in Flask here, but it didn't really solve my problem. My data is being passed to the html page exactly as I want it, I just want to put it in a table.
I also found Flask-Table, an extension to build the table in Python and then using it. It may end up being a solution, but I still don't see what's wrong with my code.
Didn't find anything useful in the Bootstrap docs either.
Any help greatly appreciated!
You're missing a few <tr> and <td> tags:
<table class="table">
<thead>
<tr>
<th>name</th>
<th>age</th>
<th>option</th>
<tr>
</thead>
<tbody>
{% for person in people %}
<tr>
<td>{{ person.name }}</td>
<td>{{ person.age }}</td>
<td>{{ person.option }}</td>
</tr>
{% endfor %}
</tbody>
</table>
You're aiming for a table-row (<tr>) per user, and some table-data (<td>) for each of their attributes. You've also got a {% endblock %} where you should have an {% endfor %}.

Passing variables to a Django template

I am new to Django and have a basic question. I created a Django template, and would like to pass external variables to it, which controls colspan tag. I tried several times, but could not deliver the variable. I appreciate any help.
Python Code:
def getdjtemplate(th_span="1"):
dj_template ="""
<table class="out_">
{# headings #}
<tr>
{% for heading in headings %}
<th colspan={{ %s }}>{{ heading }}</th>
{% endfor %}
</tr>
</table>
"""%(th_span)
return dj_template
I think I should not use this, but not sure how to fix it.
<th colspan={{ %s }}>{{ heading }}</th>
You are just returning a string. You must call the django methods to render the template:
from django.template import Context, Template
def getdjtemplate(th_span="1"):
dj_template ="""
<table class="out_">
{# headings #}
<tr>
{% for heading in headings %}
<th colspan={{ th_span }}>{{ heading }}</th>
{% endfor %}
</tr>
</table>
"""
t = Template(dj_template)
headings = ["Hello"]
c = Context({'headings':headings, 'th_span':th_span})
return t.render(c)

Categories