Doing auto redirect using CherryPy - python-2.7

I've just discovered CherryPy. I am going through the tutorial, so far so good. While doing it I wanted to create a "BUSY DOING WORK" splash screen, essentially I have a python function that for example updates an sqlite table with 10000 records. What I want to do is get CherryPy to display a busy.html page while the database is being updated, when the database operation completes I want to redirect the user back to the main.html page.
So far I have only come across
dev update_db(self):
#Code to update the database goes here
return "busy.html"<----show user that work is being done
#database has completed
CherryPy.redirect "main.html"
But return simply exits the function. Is there anyway of doing presenting the user with a temporary splashscreen, while the database is being updated then returning the user back to another page once its complete.
I suppose an alternative is to have a message flash across the top of the existing page, But I don't know if CherryPy has a flash message feature much like Flask.

IMHO, you can achieve this with generators and here is a link from latest (v3.8) cherrypy documentation. However, you should take into account the following issue in the docs
Streaming generators are sexy, but they play havoc with HTTP. CherryPy allows you to stream output for specific situations: pages which take many minutes to produce, or pages which need a portion of their content immediately output to the client. Because of the issues outlined above, it is usually better to flatten (buffer) content rather than stream content. Do otherwise only when the benefits of streaming outweigh the risks.
Generators have some limitations as written in the documentation
you cannot manually modify the status or headers within your page handler if that handler method is a streaming generator, because the method will not be iterated over until after the headers have been written to the client. This includes raising exceptions like HTTPError, NotFound, InternalRedirect and HTTPRedirect. To use a streaming generator while modifying headers, you would have to return a generator that is separate from (or embedded in) your page handler.
Because the headers have already been written to the client when streaming, raising redirection exception cannot help to redirect to different page after your long running task. If I were you, I would yield this
<meta http-equiv="refresh" content="0;URL='/anotherpage'" />
or this at the final yield
<script>window.location.href="/anotherpage";</script>
I coded and example for you. I hope this gives you an idea.
# encoding: utf-8
import time
import cherrypy
class Root(object):
#cherrypy.expose
def index(self):
content = '''<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("body").append("<p>jQuery Ready</p>");
setTimeout(function(){
$("body").html("Redirecting Please Wait...")
}, 2500);
});
</script>
</head>
<body>
<p>Page Content1</p>
<p>Page Content2</p>
<p>Page Content3</p>
<p>Page Content4</p>
<p>Page Content5</p>
<p>Page Content Final</p>
</body>
</html>
'''
for line in content.split("\n"):
yield line
time.sleep(1)
else:
yield '''<meta http-equiv="refresh" content="5;URL='/anotherpage'" />'''
index._cp_config = {'response.stream': True}
#cherrypy.expose
def anotherpage(self):
return "Another Page"
cherrypy.quickstart(Root(), "/")

Related

How to block internet explorer on my Django web app?

I'm working on a web application that does not work well with Internet Explorer (web socket, json, security issues).
For now, before my application works with IE:
How can I refuse connections coming from Internet Explorer client ?
Thank you
Create a middleware where you're parsing the request.META['HTTP_USER_AGENT']. If you found that the user use IE, give him a nice message (e.g a notification or a little alert box) to says him that your site isn't optimized for his browser :)
Some code example: Django way
middleware.py (see the doc for more information)
class RequestMiddleware():
def process_request(self, request):
if request.META.has_key('HTTP_USER_AGENT'):
user_agent = request.META['HTTP_USER_AGENT'].lower()
if 'trident' in user_agent or 'msie' in user_agent:
request.is_IE = True
else:
request.is_IE = False
# or shortest way:
request.is_IE = ('trident' in user_agent) or ('msie' in user_agent)
your base template:
{% if request.is_IE %}<div class="alert">Watch out! You're using IE, but unfortunately, this website need HTML5 features...</div>{% endif %}
And then add it to your middlewares list.
Optimized: pure HTML way
If you only want to display a message like what I've done, you can use a HTML conditional comment:
<!--[if IE]> <div class="alert">...</div><![endif]-->
There is another way! Just use settings variable DISALLOWED_USER_AGENTS, and make sure that CommonMiddleware is installed on your site.
For example
import re
DISALLOWED_USER_AGENTS = (re.compile(r'msie\s*[2-7]', re.IGNORECASE), )
Cheers!

Django Socketio 101

I try to implement a chat with django-socketio in my django app.
First, I have to learn about django-socketio, so I read the README of https://github.com/stephenmcd/django-socketio
I really want to get the basis of it. So I try to create a simple thing where a message will be rendered through socketio.
My events.py:
#events.on_connect
def first_connect(request, socket, context):
socket.broadcast_channel("my message")
My view:
def chat(request):
return render_to_response('chat.html', {} ,context_instance=RequestContext(request))
My url:
url(r'^chat/$', 'projet.views.chat'),
My html:
<head>
{% load socketio_tags %}
{% socketio %}
<script>
var socket = new.io.Socket();
socket.connect();
socket.on('connect', function(){
socket.subscribe('my_channel');
});
</script>
</head>
When I go to localhost:8000/chat, nothing appear.
So it's probably very basic, but how can I do to simply send a message through my socket and render it in my html when I connect to it?
I really want to learn about it, so if someone has a tutorial about django-sockieto, I would really appreciate it.
You can look at Cody Soyland blog entries here and here. It may be outdated but I think you can get the feeling of what should be going on there. Also it's not about django-socketio.

Attaching a .png file to an email sent by satchmo

In a Satchmo Store, I need to attach a small .png (a barcode) to an email that django sends on completion of the order. The email is formatted in HTML using send_order_confirmation() which calls send_store_mail() (both part of satchmo.) Neither of these functions offer the ability to attach a file (I think) so should I just re-write them? I was wondering if it is possible/better to do this using signals. Maybe rendering_store_mail() ?
By the way, the barcode would be dynamically generated, so there's no way of having a link to a file on a server somewhere.
Many thanks,
Thomas
well I too had to add extra infos to the confirmation emails, only text though. So this would be the very easy way to add extra-stuff to emails using signals, which IMHO, is the best approach to do it. Always use signals if you can avoid overriding the satchmo-core ;-)
define your listener to add some context for the rendering. In this case I'm adding the contents of an extra notes field, and the barcode for this order, supposing there is a function named get_barcode_img(<order>), to the context. I'm supposing here too, that the get_barcode_img function would return not just a png, but something like a MIMEImage (like from email.MIMEImage import MIMEImage) to be able to just include it inline. Also, there might be more infos needed, like a MIME-header for the img.
# localsite/payment/listeners.py
def add_extra_context_to_store_mail(sender,
send_mail_args={}, context={}, **kwargs):
if not 'order' in context:
return
context['barcode_header'] = get_barcode_header(context['order'])
context['barcode_img'] = get_barcode_img(context['order'])
context['notes'] = context['order'].notes
connect the listener to the signal somewhere where the code will be "discovered" for sure, like models.py:
# localsite/payment/models.py
from satchmo_store.shop.signals import rendering_store_mail, order_notice_sender
rendering_store_mail.connect(payment_listeners.add_extra_context_to_store_mail, sender=order_notice_sender)
override the templates locally (e.g. order_placed_notice.html) to add the new context. Be aware where you put your templates, as the path is essential for django to take your new template instead of the satchmo's one. In this case, starting from your project's root-path, there could be a templates-folder and inside it, there must be exactly the same path as in the satchmo-folder. E.g. /templates/shop/email/order_placed_notice.html ... this can be applied for any "valid" templates-folder inside an app. It's up to you to decide, where/how the templates should be organized.
<!-- templates/shop/email/order_placed_notice.html -->
<!DOCTYPE ...><html>
<head>
<!-- include the image-header here somewhere??? -->
<title></title>
</head>
<body>
...
Your comments:
{{ notes }}
Barcode:
{{ barcode_img }}"

Passing url to django to be used as variable?

So when I'm trying to pass url to django views it cuts it. For example, I have a webpage which shows statistics of downloads for users sorted by download amount. Then I want to get details about some user, for example for "Yousuke Kataoka". I press the link and go to user page. Url should be and is mysite.com/user/Yousuke Kataoka, but in the webpage I see "Details for Yousuke", it kinda cuts the url. So of course I can't get any details, because the username is cut.
Here is part of urls.py:
(r'^user/(?P<username>[*_a-zA-Z0-9./-=]+)', 'dq2.web.usermon.views.user')
And here is user.html template:
<html>
<head>
<title>Detailed information for {{usr}}</title>
<script src="/dq2/media/js/sorttable.js"></script>
</head>
<body>
<p>Detailed information for {{usr}}</p>
<table width="30%">
<tr><td>File Downloads (1HR)</td><td align="right">{{file_events_1h}}</td></tr>
<tr><td>File Downloads (24HR)</td><td align="right">{{file_events}}</td></tr>
<tr><td>File Downloads (7D)</td><td align="right">{{file_events_7d}}</td></tr>
<tr><td>File Downloads (30D)</td><td align="right">{{file_events_30d}}</td></tr>
<tr><td>Operations (1HR)</td><td align="right">{{op_events_1h}}</td></tr>
<tr><td>Operations (24HR)</td><td align="right">{{op_events}}</td></tr>
<tr><td>Operations (7D)</td><td align="right">{{op_events_7d}}</td></tr>
<tr><td>Operations (30D)</td><td align="right">{{op_events_30d}}</td></tr>
</table>
And so on..
What should I do?
Try adding a space in your regex. And are you sure you meant to have /-= in there?

Django debug console shows double GET for a single page request

I'm running the developer's Django server while writing a simple view and it seems whenever I request a page, the console shows that there are 2 GETs for the same URL. What would cause this happen? I'm not using any redirects, so I don't see how a 2nd request would be made?
EDIT: It appears to be caused by the template. Changing to a blank html file for a template resolved the issue. The question is why? I have multiple {% if %} {% endif %} sections, with no elses. Could that be an issue?
It also could be Firefox following a WC3 directive under which it's supposed to dual load if certain tags come empty or broken, for example, a without a src="" etc. That being said, I saved off the rendered HTML on receipt and moved it into a static file, where I added the same headers as the real checkout and a small DB log of all accesses.
I just stumble upon this problem and fixed it removing my img wit src=""
Please confirm, if Django is redirecting after appending slash to your url. Its the property APPEND_SLASH in your settings.py controls that.
The second request is probably caused by a mis-configured asset link - a script, style or img tag which is empty or omits the initial / and is therefore re-requesting the page.
It could be your shortcut/favicon
Do you have link rel="shortcut icon" in your page template? Comment it out to see if it removes the second request
In my case : I have the same javascript code in 2 files : one in the base template and the same one in another template. As I use ajax to not reload all the page I got the call 2x, then 4x, and 8x, ...
The solution is the use the javascript code only in mybase.html
Hereafter my js code :
<script type="text/javascript">
// Code jQuery Ici
$(document).ready(function(){
// GET
$(".ajax_onglet_get").click(function(e){
var lien = $(this).attr('href');
$('#zone_travail').fadeOut('fast', function(){
$('#zone_travail').load(lien, function() {
$('#zone_travail').fadeIn('fast');
});
});
e.preventDefault()
});
});