Django: Redirect after HttpResponse - django

I am generating a report download in a view and starting the download after processing the POST data. That means the user sends a form and the download starts:
views.py
def export(request):
if request.method == 'POST' and 'export_treat' in request.POST:
form1 = TransExport(request.POST, instance= obj)
if form1.is_valid():
...
...
response=HttpResponse(ds.xls,content_type="application/xls")
response['Content-Disposition'] = 'attachment; filename="Report_Behandlungen.xls"'
return response
What I need is a page refresh after the download (or a redirect).
How can I achieve this?

I would just do it in simple logic with javascript:
user clicks the link
/download_file_now/
and comes to /file_downloaded/ where the download starts and after 3 seconds, you just redirect the page via js
location.replace('/another_url/');
to detect if the download is ready is not easy

Related

Return HttpResponse object and render page from Django views.py

I'm new to Django and have been learning by modifying some existing code. The original code, in the views.py file, had a method that returned an HTTP Response object (lets call this resp) to the browser, on the click of a button.
I want to be able to
open a new page on a click of that button (which I am doing using the render() function)
as well as
pass resp to it (this is because the 3rd party API that I am using needs this HttpResponse object in order to work).
Is there anyway I can do this? I thought of passing resp as part of the context parameter in the render() function, but I don't understand how I can collect back the value from this context dictionary and then return it to the browser.
EDIT: This is the code in the views.py file:
def call(request):
"""Returns TwiML instructions to Twilio's POST requests"""
response = Dial(caller_id=settings.TWILIO_NUMBER)
# If the browser sent a phoneNumber param, we know this request
# is a support agent trying to call a customer's phone
if 'phoneNumber' in request.POST:
response.number(request.POST['phoneNumber'])
else:
# Otherwise we assume this request is a customer trying
# to contact support from the home page
response.client('support_agent')
response = str(response)
probe = response.find(">")
response = response[:probe+1] + "<Response>" + response[probe+1:] + "</Response>"
print('response:', response)
context = {'response': HttpResponse(response)}
return render(request, 'browser_calls/call_in_progress.html', context) # originally HttpResponse(response) was being returned here because that was required for the call to be placed
What you can do is return all the variables from that scope using locals()
context = locals()
return render(request, template, context)

Django: uploaded file not available in request.FILES unless you call request.body first

I used fileupload jquery script to upload a small simple file. On the Django server side, I received the POST, but request.FILES is empty.
However, if I call request.body before calling any other request's APIs/macros, the uploaded file info then appears in request.FILES.
Is this the kind of quantum theory in HTTP? Can anyone kindly explain it? What is the proper way to handle the uploaded file?
The problem is not unique to file upload. It happened to all ajax posts. I suspect that some sort of settings may be required in order to have the underlying system automatically process incoming stream and construct objects out of it.
Here is server side code segment:
class FileUploadView(View):
def post(self, request):
assert isinstance(request, HttpRequest)
# temporary solution in order to trigger the underlying system to
# construct objects from incoming stream.
bb = request.body
field_name = 'data_file'
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
filename = form.files[field_name].name
if FileDataSource.allowed_file_type(filename):
self.save_file(filename,
request.FILES[field_name],
UPLOAD_FOLDER)
self.register_datasource(filename, UPLOAD_FOLDER)
return self.reply_features(filename=filename)
else:
pass
and here is client side jquery:
$("#fileupload").fileupload({
dataType: 'json',
success: function (data) {
console.log(data)
},
error: function(data) {
}
});

Alternative of Requests in django

In my project I'm trying to hit a url(which is running in same project) in my view.
so in simplest way I can explain here.
#login_required
def my_api_view(request):
if requests.method == 'GET':
# do stuff
return JsonResponse()
# and its url is `/api/get-info/`
another view which is consuming above api
#login_required
def show_info(request):
url = get_base_url + /api/get-info/ # http://localhost:8000/api/get-info/
r = requests.get(url)
return HttpResponse(r.json())
Now I have to use same session (login required) so when I hit the url using requests it complains that user is not loggedin which is obviously correct.
How can I do this elegantly and efficienty. session use of logged in user. (I dont want to call the view as a function, I want to hit the api-url end point and consume.
PS: we have something similar in django Test self.client.get(...)
Just call that view function and pass the request object as parameter to it.
#login_required
def show_info(request):
r = my_api_view(request)
return HttpResponse(r.json())
Or a better option would be to simply separate the logic into a separate function, as mentioned by #koniiiik in the comments.
EDIT: Or if you really want to hit the URL endpoint, you can simply pass on the cookie values to the request you make.
#login_required
def show_info(request):
url = get_base_url + "/api/get-info/" # http://localhost:8000/api/get-info/
r = requests.get(url, cookies=request.COOKIES)
return HttpResponse(r.json())

Flask, jinja2: Is it possible to render part of a page with render_template() without affecting the rest of the page

I have a home page that includes a few different forms one of which is an edit profile form. I am handling the forms with wtfforms and have a child template called edit_profile.html which renders both the original form and any errors returned by the edit_profile view function. What I am trying to do is this:
In the event that errors are returned: to render the child template edit_profile.html without disturbing the rest of the page.
At the moment there is a home page view function:
#app.route('/', methods=['GET','POST'])
def home():
cur = g.db.execute(some_select_statement)
data = cur.fetchall()
some_var = some_function(data)
ep_form = EditProfile()
return render_template('home.html', some_var=some_var, ep_form=ep_form)
And then a function that deals with the editing of the profile:
#app.route('/edit_profile', methods=['GET', 'POST'])
def edit_profile():
ep_form = EditProfile()
if ep_form.validate_on_submit():
# In here is the code that handles the new profile data
return render_template('edit_html', ep_form=ep_form)
At the moment when an error is returned, most of the page is returned except that which draws upon 'some_var' to be rendered. I know that I can use Ajax to render the WTF error values and leave the rest of the page untouched but I was wondering if there was a way to do it with only the use of Flask and Jinja.
If any error is encountered while processing the form data, redirect to the home endpoint with the POST data (using code 307).
#app.route('/edit_profile', methods=['GET', 'POST'])
def edit_profile():
ep_form = EditProfile()
if ep_form.validate_on_submit():
# If the data is validated and good
# In here is the code that handles the new profile data
return render_template('edit_html', ep_form=ep_form)
else:
# If any errors are encountered, redirect
# back to the home endpoint along with POST data
# using code 307
return redirect(url_for('home'), code=307)
Now in the home endpoint, we need to handle the POST data that might get redirected from edit_profile.
#app.route('/', methods=['GET','POST'])
def home():
# fetch data from DB, other values
ep_form = EditProfile()
# We need to call validate_on_submit so that
# the data is validated and errors are populated
if request.method == "POST":
ep_form.validate_on_submit()
return render_template('home.html', some_var=some_var, ep_form=ep_form)
In this way, home view function will have access to the form data, validate it and can show the errors.

payment processing with django

I am trying to build code that allows people to pay for the services that they get from my website. I have built the form using the forms.Form model available in django. I have also used the following pattern to build my view.
if request.method == 'POST'
form = ContactForm(request.POST)
if form.is_valid(): # All validation rules pass
conn = urllib2.Request(payment_gateway_url,urllib.urlencode(my_dat_in_dict))
f= urrlib2.urlopen(conn)
all_results=f.read()
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render(request, 'contact.html', {
'form': form,
})
The problem i am facing is that my forms get submitted OK and the payment gateway responds back to me with a whole bunch of html that helps the user to choose the credit card details etc in the response to this form POST(details that i am not collecting on my website). I can see this in the all_results (f.read()).
My question is that how do i show the user this page, since i get this as a result of my form POST. Should i save this response in a html file and HTTPResponseredirect to that page. I am assuming that HTTPResponseRedirect is more for a complete transaction and not the intermediate responses.
So, basically how do i handle the situation where the user will get sent to the payment gateway site and then after completing the proceedings come back to my site?
thanks
First off, I would say, if you live in the US, check out Stripe (or something similar). The way you are describing your payment process seems a bit overly complicated.
With that said, if (and I doubt this is the case), the HTML returned from the most is in the correct format for display on your website, you can just stick it in to an HttpResponse (must be a sprint)
return HttpResponse(html)
Otherwise, use something like BeautifulSoup, Scrape.py, or something similar to format it IN RAM, and then use HttpResponse. I would not write it to the file system for modification.