Printing dynamic django view template - python

I'm working on a django app. I have a page that displays a log of items, and each item has a "Print label" link. At the moment, clicking the link displays the label for that particular item in a popup screen, but does not send the label to a printer. The view function behind the "Print label" link is shown below:
#login_required
def print_label(request, id):
s = Item.objects.get(pk = id)
return render_to_response('templates/label.html', {'s': s}, context_instance=RequestContext(request))
The HTML for the label is shown below:
{% load humanize %}
<head>
<style type="text/css">
div{
min-width: 350px;
max-width: 350px;
text-align: center;
}
body{
font-family: Arial;
width: 370px;
height: 560px;
text-align: center;
}
</style>
</head>
<body>
<div id="labelHeader">
<img src="{{ STATIC_URL }}img/label-header.png" width="350px">
</div>
<hr/>
<p></p>
<div id="destinationAddress">
<span style="font-size: xx-large; font-weight: bold;">{{ s.item_number }}</span>
</p>
DESTINATION:
<br/>
<strong>{{s.full_name}}</strong><br/>
<strong>{{ s.address }}</strong><br/>
<strong>{{s.city}}, {{s.state}}</strong><br/>
<strong>Tel: {{s.telephone}}</strong>
</div>
<p></p>
<hr/>
<div id="labelfooter">
<img src="{{ STATIC_URL }}img/label-footer.png" width="350px">
</div>
</body>
My question is, how can I also send the label displayed to a printer in the same function? I researched and found some libraries (like xhtml2pdf, webkit2png, pdfcrowd, etc), but they'll create a pdf or image file of the label and I'll have to send it to a printer. Is it possible to send straight to a printer without creating a pdf copy of the label? If so, please show me how to achieve this.
Your answers and suggestions are highly welcome. Thank you.

Presumably, as this is a Django app, it's the client's printer that you need to use. The only way to do this is to tell the user's browser to print. You will need to use Javascript for this: window.print().

Related

How do you create a stream inside a Flask webpage? [duplicate]

This question already has answers here:
Display data streamed from a Flask view as it updates
(3 answers)
Closed 2 years ago.
I'm running a bot and I'm trying to output the bot's logs to a simple webpage as a stream of HTML content (each log is sent as <p>{log}</p>). If I output the stream to route "/log_stream" and then go to that route, I can see the logs and they update and everything works as expected. However, I can't figure out how to incorporate that stream in another webpage. I tried embedding it using an <iframe> with the "/log_stream" route as the src but then the iframe wouldn't render at all. Any idea how to make this work?
NOTE: Please don't mark this as a duplicate of Display data streamed from a Flask view as it updates The answer there is either outdated or incorrect. Although you can't update the template directly after it's been rendered on the server, you definitely can embed dynamic content in that template using an iframe or img, like in this tutorial where he uses an image dynamically to create a video stream. Not being able to dynamically update the template itself is NOT the same thing as not being able to dynamically update the content IN that template.
app.py:
from flask import Flask, render_template
from threading import Thread
from bot import Bot
from logger import Logger
from config import config
application = Flask(__name__)
logger = Logger()
#application.route('/')
def index():
return render_template('index.html.jinja', products=config['targets'], status='running')
#application.route('/log_stream')
def log_stream():
return logger.printerStream()
if __name__ == '__main__':
bot = Bot(logger)
botThread = Thread(target=bot.run)
botThread.start()
application.run(host='0.0.0.0', debug=True)
logger.py (relevant parts):
def getLogHTML(self, logObj):
if logObj['type'] == INFO:
return "<p style=\"color:green\">"+logObj['text']+"</p>\n"
if logObj['type'] == WARN:
return "<p style=\"color:yellow\">"+logObj['text']+"</p>\n"
if logObj['type'] == ERROR:
return "<p style=\"color:red\">"+logObj['text']+"</p>\n"
if logObj['type'] == EXCITE:
return "<p style=\"color:blue\">"+logObj['text']+"</p>\n"
return "<p style=\"color:white\">"+logObj['text']+"</p>\n"
def printerStream(self):
self.isStreaming = True
self.logs = self.getStoredLogs()
self.logs.extend(self.secondaryLogs)
self.storeLogs(self.secondaryLogs)
self.secondaryLogs = deque()
def generate():
try:
while True:
if len(self.logsToStore) > 0:
self.storeLogs(self.logsToStore)
self.logsToStore = deque()
nextLog = self.getNextLog()
nextLogHTML = self.getLogHTML(nextLog)
yield nextLogHTML
except GeneratorExit:
self.isStreaming = False
self.isStreaming = False
return Response(generate(), mimetype='text/html') # maybe text/html?
index.html.jinja:
<!doctype html>
<head>
<title>Title</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
body {
color: green
}
.title {
display: flex;
flex-direction: row;
justify-content:center
}
h1 {
margin-bottom: 6px;
}
.row {
display: flex;
}
.column {
flex: 50%
}
</style>
</head>
<body>
<div class="title">
<h1>Title</h1>
<h2>Subtitle</h2>
</div>
<div class="row">
<div class="column">
</iframe src="{{ url_for('log_stream')}}">
</div>
<div class="column">
<div class="row">
<div class="column">
<p>Products: </p>
</div>
<div class="column">
{% for product in products %}
<p>{{product.name}}</p>
{% endfor %}
</div>
</div>
<div class="row">
<div class="column">
<p>Status: </p>
</div>
<div class="column">
<p>{{ status }}</p>
</div>
</div>
</div>
</div>
</body>
Actually, I solved this by adding styling to the <iframe>. Changing it to:
<iframe frameborder='0' noresize='noresize'
style='position: absolute; background: transparent; width: 100%; height:100%;'
src="{{ url_for('log_stream')}}"
frameborder="0"></iframe>
accomplished pretty much what I wanted!

Delaying backgroung image in web2py view

I would like to give the background-image it's own class so I can use the javascript code on it. However, if I remove it from the current div the background-image can not be displayed because it is the background-image for this div.
This is the web2py View:
{{extend 'layout.html'}}
{{for color in bg:}}
<div class="project_video" style="background-image: url('{{=URL('download', args=color.bg_picture)}}')">
{{pass}}
<video class="movie" style="width: 100%;" src="{{=URL('download', args=videos.clip)}}" autoplay poster="{{=URL('static', 'images/tabla_loading_poster.png')}}" onended=videoEnded()></video>
<div class="objects" hidden>
{{for pic in pics_objects:}}
<img src="{{=URL('download', args=pic.pictures)}}"/>
<audio autoplay src="{{=URL('static', 'images/pop.mp3')}}"></audio>
{{pass}}
</div>
</div>
Of course if I use the javascript on the project_video class it will apply to the entire div. not only to the background-image.
This is the web2py Controller for the above View:
def game():
videos = db.vid(request.args(0,cast=int)) or redirect(URL('index'))
bg = db(db.back.owner_id==request.args(0)).select()
pics_objects = db(db.pic.owner_id==request.args(0,cast=int)).select()
return locals()
This is the javascript bellow but, as I mentioned, this will hide the whole div and what I want to hide is the background-image only:
<script>
$(function(){
$('.project_video').hide();
});
$(window).load(function() {
$('.project_video').delay(6000).show(0);
});
</script>
I would appreciate any advise.

Adapt a Macro for Plone to display nothing if specific folder does not exist?

I have a macro for a Researcher Profile on Plone that I would like to adapt to display nothing if the desired folder does not exist. As it is now, if the "selected-publications" folder does not exist, it throws an error. Is it possible to make the macro display nothing if the "context/selected-publications/..." is empty or does not exist? Here is the code I have so far:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" i18n:domain="RDSLocal">
<body>
<div id="publications" metal:define-macro="publications" tal:omit-tag="">
<!--publications-->
<h2>Publications</h2>
<ul style="list-style: none; margin-left: 0px; margin-right: 0px;">
<tal:block tal:repeat="publication context/selected-publications/getFolderContents">
<li><tal:block tal:content="publication/Authors"/> (<tal:block tal:content="publication/publication_year"/>) <a tal:attributes="href publication/getURL" tal:content="publication/Title"/></li><br />
</tal:block>
</ul>
</div>
</body>
</html>
Use tal:define and tal:condition to get and check the publications exist before you iterate through them with tal:repeat. Taking your code verbatim as a baseline:
<div id="publications" metal:define-macro="publications" tal:omit-tag="">
<!--publications-->
<h2>Publications</h2>
<ul style="list-style: none; margin-left: 0px; margin-right: 0px;"
tal:define="publications nocall:context/selected-publications|nothing"
tal:condition="publications">
<tal:block tal:repeat="publication publications/getFolderContents">
<li><tal:block tal:content="publication/Authors"/>
(<tal:block tal:content="publication/publication_year"/>)
<a tal:attributes="href publication/getURL"
tal:content="publication/Title"/></li><br />
</tal:block>
</ul>
</div>
This is a common idiom in Zope templates. If you look in Plone's source code you'll find a treasure trove of examples of this technique that you can plunder.
Maybe you want to hide the H2 if no publications exist? If so put the tal:define and tal:condition on the div instead.
Are you calling this from some other template? If not there's no need to define the snippet as a macro.

Display a ‘loading’ message while a time consuming function is executed in Flask

I’m still relatively new to Flask, and a bit of a web noob in general, but I’ve had some good results so far. Right now I’ve got a form in which users enter a query, which is given to a function that can take anywhere between 5 and 30 seconds to return a result (looking up data with the Freebase API).
The problem is that I can’t let the user know that their query is loading during this time, as the results page only loads once the function finishes its work. Is there a way I can display a loading message while that's going on? I found some Javascript that could display a loading message while page elements are still loading, but my waiting period happens before ‘render_template’.
I knocked together some example code, just to demonstrate my situation:
Python:
from flask import Flask
from flask import request
from flask import render_template
import time
app = Flask(__name__)
def long_load(typeback):
time.sleep(5) #just simulating the waiting period
return "You typed: %s" % typeback
#app.route('/')
def home():
return render_template("index.html")
#app.route('/', methods=['POST'])
def form(display=None):
query = request.form['anything']
outcome = long_load(query)
return render_template("done.html", display=outcome)
if __name__ == '__main__':
#app.debug = True
app.run()
Excerpt from index.html:
<body>
<h3>Type anything:</h3>
<p>
<form action="." method="POST">
<input type="text" name="anything" placeholder="Type anything here">
<input type="submit" name="anything_submit" value="Submit">
</form>
</p>
</body>
Excerpt from done.html:
<body>
<h3>Results:</h3>
<p>
{{ display }}
</p>
</body>
Any help would be greatly appreciated, I hope this example helps.
Add this to your index.html or js file (I'm assuming you have jQuery here, you could use standard javascript of course.):
<script type="text/javascript">// <![CDATA[
function loading(){
$("#loading").show();
$("#content").hide();
}
// ]]></script>
Add this to you html or css file:
div#loading {
width: 35px;
height: 35px;
display: none;
background: url(/static/loadingimage.gif) no-repeat;
cursor: wait;
}
You can get an adequate GIF from http://www.ajaxload.info/. Download and put it into your static folder.
Then change your submission button to call above js function:
<input type="submit" name="anything_submit" value="Submit" onclick="loading();">
and add in a loading and a content div to you base html file:
<body>
<div id="loading"></div>
<div id="content">
<h3>Type anything:</h3>
<p>
<form action="." method="POST">
<input type="text" name="anything" placeholder="Type anything here">
<input type="submit" name="anything_submit" value="Submit" onclick="loading();">
</form>
</p>
</div>
</body>
Now when you click 'Submit', the js function should hide your content and display a loading GIF. This will display until your data is processed and flask loads the new page.
This can be done by using a div that contains a 'loading gif' image. When the submit button is clicked, the div is displayed using javascript.
To implement this, you can take a look at this website: http://web.archive.org/web/20181023063601/http://www.netavatar.co.in/2011/05/31/how-to-show-a-loading-gif-image-while-a-page-loads-using-javascript-and-css/
I found the purely CSS-dependent loader very useful. It does not depend on external resources:
https://www.w3schools.com/howto/howto_css_loader.asp
This is a bit of an old topic, but I needed to deal with this problem today and came with a solution on my own. I'm running a machine learning model that recieves an image input from the user and does some magic.
Basically this is what I did.
On my index.html file, I called a loading function on my "Submit" button passing the filename, because I was going to use it later:
<form method="post" action="/loading/{{filename}}"
enctype="multipart/form-data">
<input type="submit" value="Submit!">
</form>
On Flask, I created a route just to render the loading screen before doing the time consuming task, also passing the filename ahead:
#app.route('/loading/<filename>', methods=['POST'])
def loading_model(filename):
return render_template ("loading.html", filename=filename)
And then, on loading.html, I render my .gif animation and at the end I redirect the page to the time consuming task function:
<!doctype html>
<head>
<link rel= "stylesheet" type= "text/css" href= "{{url_for('static',filename='styles/main.css') }}">
</head>
<div id="preloader">
<div id="status">&nbsp</div>
<h1 class="ml13">ANALYZING...</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.0.2/anime.min.js> </script>
</div>
<title>Title</title>
<script src="{{url_for('static', filename='main.js')}}"></script>
<script> window.location.replace('/task/{{filename}}'); </script>
And then, final step, back to Flask, call the task function:
#app.route('/task/<filename>', methods=['POST', 'GET'])
def task(filename):
# Do your stuff
return render_template ("results.html")
By doing this, the gif animation will keep playing whilst the function does its job, and then render the results or the next page you want.
You obviously have to edit the css file so that "preloader" and "status" behave like you wish, this is how I used it:
#preloader {
background-color: white;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#status {
background-image: url("lalala.gif");
background-repeat: no-repeat;
width: 800px;
height: 600px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -400px;
margin-left: -400px;
}
It worked out for me.
Brilliant #jka.ne but confusing situation.
I only needed to introduce the loading gif while a button was clicked.
My solution was:
<script type="text/javascript">
function loading(){
$("#loading").show();
window.location.href="../target_html";
}
</script>
Then:
<button type="button" class="xxx" onclick="loading();">Run</button>
Finally:
<div id="loading"></div>

to employ charts(written in python using matplolib) in html file

I have created app using django which searches the keywords entered by the user in 10 xml documents and maintains the frequency count of those words for each file. The results are returned to the user in the form of expandable hyperlinked list of filenames and the charts. My html code:
<html>
<style type="text/css">
h1 {
position: absolute;
top: 5px;
left: 200px;
}
form #Edit1 {
position: absolute;
top: 37px;
left: 410px;
}
form #Edit2 {
position: absolute;
top: 37px;
left: 840px;
}
</style>
<font size="4" face="arial" color="#0000FF">
<h1>XML Search</h1>
</font>
<br/>
<br/>
<Form Action ="/search/" Method ="POST">
<div id="Edit1">
<INPUT TYPE = 'VARCHAR' name ='word' VALUE ="" size = "50">
</div>
<div id="Edit2">
<INPUT TYPE = "Submit" VALUE = "Search">
</div>
<br/>
<hr/>
{% csrf_token %}
</FORM>
{% if list1 %}
<input type="text" name="word" value="{{ word }}" />
<ul>
{% for l in list1 %}
<li>{{l.file_name}}, {{l.frequency_count}}</li>
{% endfor %}
</ul>
<br/>
# -- charts to be employed -- #
{% endif %}
</html>
this html page is redirected from views.py file. Now, I want to write the code for charts using matplotlib in this html code. As the code to create charts using the mentioned library is written in python, so how can I write this python code in the above html file or if there is any other way out, so please tell?
Note:
I have made use of google charts and that are working perfectly fine but I want to make this app internet independent, so please do not suggest me google charts.
Please Help , I'm new to charts and django.
The matplotlib cookbook has an entry on using matplotlib with django.
It boils down to the following:
In urls.py you add an entry for a png with a link to a new view.
In your new view you create a HttpResponse with content_type image/png
Using matplotlib you write a figure as png to the aforementioned HttpResponse
A straight copy/paste from the cookbook should get you going.
Perhaps you can break the problem into bite size pieces to avoid learning three things at once:
Add a static .png to your page
Add a dynamic .png to your page via urls.py and a new view
Create a figure in Matplotlib (offline)
Put the matplotlib figure from step 3 into the dynamic image from step 2

Categories

Resources