jQuery/Django retrieving file - python

I have seen many answers to questions like this, but none has solved my problem...
I want to produce a pdf in the backend and then download it to the user.
So I have a basic blank page with a button. For that button there is a jQuery function:
$.post("{% url 'printReport' %}",
{
'params' : JSON.stringify({
'reportcode' : 'HelloWorld',
})
}, function(data, status) {
$("#testZone").text(data)
});
On the server side, I produce the pdf and save it locally in the server folder. This goes perfect.
Then, in the views file I have this:
def printRreport(request):
if request.method=="POST":
res = producePdf(request) #works fine! the PDF is birght an shiny, saved on the server
response = HttpResponse(res.data,content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="report.pdf"' #setting response headers
return response
where res.data is actually open(pdf_path,'r').read()
this is 70% fine, because the browser actually receives the pdf data inside the request response (I can see it on the dev console). It's 30% wrong because this does not give me a download dialog and does not allow me to save a pdf file on the client side.
What is wrong here? In my case I opted by using a POST method, I know it's debatable, but I don't think that is the problem...
Edit: I found a solution for this, maybe not optimal, but it works.
I marked below the answer I ended up following. I kept the code above, but I decided to generate the pdf file on the first view (which receives the POST request), then redirect the user to another view where it would download it. And it works!
I'll still check this as suggested by Abdul though.
Thanks!

Instead of using HttpResponse try using FileResponse:
from django.http import FileResponse
def printRreport(request):
res = producePdf(request)
file_ptr = # something that would get you something like open(pdf_path,'rb')
return FileResponse(file_ptr)
Now in your javascript the problem is you are making the request as ajax and the content is with javascript, an easier thing would be to let your browser handle the url (It is a file download anyway no need for ajax):
var link = document.createElement("a");
link.download = "Report";
link.href = "{% url 'printReport' %}";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
Note: If you don't need to run this dynamically consider just an anchor with the url. Instead of javascript.

Related

Python urllib2 response 404 error but url can be opened

I came across a situation when I used Python Requests or urllib2 to open urls. I got 404 'page not found' responses. For example, url = 'https://www.facebook.com/mojombo'. However, I can copy and paste those urls in browser and visit them. Why does this happen?
I need to get some content from those pages' html source code. Since I can't open those urls using Requests or urllib2, I can't use BeautifulSoup to extract element from html source code. Is there a way to get those page's source code and extract content form it utilizing Python?
Although this is a general question, I still need some working code to solve it. Thanks!
It looks like your browser is using cookies to log you in. Try opening that url in a private or incognito tab, and you'll probably not be able to access it.
However, if you are using Requests, you can pass the appropriate login information as a dictionary of values. You'll need to check the form information to see what the fields are, but Requests can handle that as well.
The normal format would be:
payload = {
'username': 'your username',
'password': 'your password'
}
p = requests.post(myurl, data=payload)
with more or less fields added as needed.

Sending GET query using Javascript to GAE to redirect to another page

On GAE (Python) I'm trying to send a GET request from local javascript and on receipt of the request redirect to another page. This is my code:
Local Javascript sending the POST:
$.get("/editor");
The Python on GAE
class Editor(webapp2.RequestHandler):
def get(self):
template = jinja_environment.get_template('index.html')
self.response.out.write(template.render())
app = webapp2.WSGIApplication([('/', StartScreen), ('/editor', Editor)],
debug=True)
I can type in the url /editor in the url bar and it does take me there. Why does my javascript GET request not activate the Editor handler and open /editor?
I am not sure if I understand the problem, but still give it a try:
The current way to use jQuery.get() should call the server but throw away the response, so you will see nothing of it in the browser.
You want at least to do:
$.get("/editor", function(response) {
document.location.href = 'another page';
});
where another page is where you want to redirect to. Then this still throws away what you content you get from the server. (response will be some HTML ... I am not sure how you want to get a location from that.) So I wonder if a simple HTML-link would just do what you want.

python-ajax prevent view source response data

i'm coding python using flask framework.
The data response from server keep showing up when i use "view-source" from browsers.
html:
$('li.channel, div.channel-in-top').on('click', function(e){
$.getJSON($(this).find('a').attr('href'), function(data){
...
}
}
server code for response:
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
return current_app.response_class(json.dumps(c), mimetype='application/json; charset=UTF-8')
c is an array of some data.
I've tried return only c, jsonify(c)
Every time when i use view-source from browser (chrome, firefox), it shows the whole data c that is return.
I've visited some website using ajax (not python thou) and see that before or after trigger ajax, view-source can just see the html as usual
I just found out the real problem.
It's about the html5' history.pushState
The ajax of flask-Python itself is doing fine

Posting JSON and python Flask - any techniques to use the Werkzeug debugger?

Alright, I'm working with a RESTful backend on my project, and submitting data via jquery.
I must say the werkzeug debugger is excellent for debugging specially when you're a terrible python programmer as me. You throw an exception on purpose where you want to investigate, and inspect the code and variables using the html the debugger rendered.
However when you send a post request instead of a get, if you throw an exception on the backend code, of course, the browser won't render the response text.
Is there any technique I can use to render the response text, considering it has javascript and everything?
I'm trying different things such as trying to inject the response text into a popup window, like:
$.postJSON = function(url, data, callback, error_callback) {
return jQuery.ajax({
'type': 'POST',
'url': url,
'contentType': 'application/json',
'data': JSON.stringify(data),
'dataType': 'json',
'success': callback,
'error': error_callback
});
};
$.postJSON('/the_uri', {'foo': 'bar'},
function(response) {
var a = 0;
},
function(response) {
var html = response.responseText;
var my_window = window.open('', 'mywindow1', 'width=350,height=150');
$(my_window.document).find('html').html(html);
});
});
But this won't take care of the javascript very well.
Does anyone have any suggestion?
Your approach was nearly correct. I am using the following code to open the response text in a new window (not specific to Werkzeug or Flask at all):
var w = window.open('', 'debug_stuff', 'width=540,height=150');
w.document.open();
w.document.write(response.responseText);
w.document.close();
The last line is the most important. Without it, the code would behave as yours -- it would not execute any JavaScript, because the browser doesn't know the DOM has been fully loaded.
Not javascript, but have you tried to use Firebug, you can use the option for viewing the response in a new tab (Open Response in New Tab).
If you're ready to make some changes on both the client and the server code, you can try this. In your error callback you would re-send the JSON data but as a synchonous form submission. You would create the form using jQuery, give it an input tag and put your JSON in that and submit the form. Something like:
$('<form method="post" style="display:none;">')
.attr('action', 'xxx')
.append(
$('<input>').val(JSON.stringify(data))
).appendTo('body')
.submit();
On the server-side, you would have to accept JSON the regular way when the request's content type is application/json and as form data, eg:
json_string = request.form.get('__json')
if json_string:
data = json.loads(json_string)
I have never tried this but I know the problem you're having and it can waste a lot of time. If you try it I'd like to know how it works out.
Markus' answer works perfectly. thanks so much! this saved me so much hassle.
also consider assigning your handlers to a jqxhr object
http://api.jquery.com/jQuery.post/#jqxhr-object
var jqxhr = $.post(...)
then you would write to your new window
w.document.write(jqxhr.responseText);

how to publish photos to facebook without using facebook sdk but only by POST to the URL ..?

In python facebook SDK , we are missing to upload photos , rather i want to upload photos without using the existing SDKs ..
so how can implments thsese steps in python ??
You can publish a photo to a specific, existing photo album with a POST to http://graph.facebook.com/ALBUM_ID/photos.
curl -F 'access_token=...' \
-F 'source=#file.png' \
-F 'message=Caption for the photo' \
https://graph.facebook.com/me/photos
This isn't a place to get work done cheaply but to learn about programming, so doubtful that someone will do your work for you if he doesn't already have the code lying around.
Anyhow a few pointers: Get yourself Tamper Data or a similar plugin for whatever browser you're using and document all the data that is sent when you're doing the task manually. Afterwards you just have to use the Python urllib lib to imitate that and parse the html documents for the non static parts you need.
No idea about facebook (no account) but you'll presumably have to login and keep cookies, so a small example of something pretty similar I had lying around. First use the login site to login and then maneuver to the site I'm interested in and get the data..
def get_site_content():
def get_response(response):
content = response.info()['Content-Type']
charset = content[content.rfind('=') + 1:] # ugly hack, check orderly
return response.read().decode(charset)
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
data = urllib.parse.urlencode({ "log" : "1", "j_username" : USERNAME, "j_password" : PASSWORD })
opener.open("url", data)
data = urllib.parse.urlencode({ "months" : "0" })
resp = opener.open("url2", data)
return get_response(resp)
You can use urllib2 or the poster module to make post requests, take a look at these questions:
python urllib2 file send problem
Using MultipartPostHandler to POST form-data with Python

Categories

Resources