Can django-piston module create upload image restful webservice - django

I trying to restful server that one can upload image, By use django-piston I can put,get,post information restfully but don't know how to upload image.

pretty much.
technically it's just a http post.

On the one hand, yes. If you have the image data, it's possible to send it via post to a handler that knows how to handle it; if you do it right, it should, theoretically, be available in request.FILES to your handler. Simple HTTP.
On the other hand, no. In order to do an AJAX upload like this, you would have to somehow get the image data without the user actually submitting a form. This is why "ajax upload forms" are so difficult to implement, and usually use tricks like hidden iframes to do their stuff.
To the best of my knowledge, only Firefox and its gecko kin allow this kind of access to a file field's binary content, via the File object's getAsBinary() method.

You can certainly do the POST. The file(s) will be available in the request.FILES (piston won't get in the way of this).
In order to do the PUT, we'll have to make some changes to piston to support the x-method-override header. That's what I do to allow PUT and DEL from flash. ( Don't forget to add the header when you do the POST to make it get interpreted as a PUT )
Here's some example middleware:
class x_http_methodoverride_middleware():
def process_request(self, request):
if 'HTTP_X_HTTP_METHODOVERRIDE' in request.META:
newMethod = request.META['HTTP_X_HTTP_METHODOVERRIDE']
if 'PUT' == newMethod.upper():
request.method = 'PUT'
request.META['REQUEST_METHOD'] = 'PUT'
request.PUT = request.POST
if 'DELETE' == newMethod.upper() or 'DEL' == newMethod.upper():
request.method = 'DELETE'
request.META['REQUEST_METHOD'] = 'DELETE'
request.DELETE = request.POST
( the code is from an open piston ticket here http://bitbucket.org/jespern/django-piston/issue/83/use-x-http-method-override-to-override-put )

You can find two answers here: http://groups.google.com/group/django-piston/browse_thread/thread/6f3f964b8b3ccf72/bd1658121bb1874c?show_docid=bd1658121bb1874c&pli=1
One way is to use request.FILES to get the filename, and then to save the image:
def create(self, request, nickname):
name = request.FILES["image"].name
image = PIL.Image.open(request.FILES["image"])
image.save(SOME_PATH+name)
return rc.ALL_OK
The second suggestion is to define an Image model and an ImageForm form, and use those:
def create(self, request, nickname):
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
Image.objects.create(image=form.cleaned_data['image'])
return rc.ALL_OK
return rc.BAD_REQUEST
WARNING: I haven't tested either of these methods!

Related

Force TemporaryFileUploadHandler on specific request

I need to process an uploaded file with GeoDjango. According to the documentation, I should use Datasource() constructor from GDAL.
Problem is that size of uploaded shapefiles can be less than 2.5 MB, so MemoryFileUploadHandler is used by default and thus I can't access to a filepath required by Datasource().
I decided to override request.upload_handlers for my specific view, with only "django.core.files.uploadhandler.TemporaryFileUploadHandler" because I don't need to create a subclass (for now), but I get the following error : You cannot set the upload handlers after the upload has been processed.
Here is my piece of code:
def home(request):
request.upload_handlers = ["django.core.files.uploadhandler.TemporaryFileUploadHandler"]
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
else:
form = UploadFileForm()
return render(
request,
'app/index.html',
{
'title':'HOME',
'form': form,
}
)
What am I doing wrong ? Also, should I create a subclass for a custom handler anyway ?
the problem is when the function is called django already use the upload_handler so it's to late to change it.
I remember you might be able to still change it if you disable csrf for the function. (Also see: Where/how to replace default upload handler in Django CBV?)
Another possibility would be writing your own upload handler or maybe a middleware that changes the upload handler depending on the path.

Is there a more elegant way to write this django view?

I've been messing around with django and I have this django view:
def handle_results(request):
if request.method == "POST" and request.is_ajax():
# Do something with the post request
elif request.method == "GET" and request.is_ajax():
# Do something with the get request
else:
# First time in this view, render first element to display
return render(
request, "result_page.html", context={"display": arr[0]}
)
The main idea is, this is supposed to be a Same Page Application, and the first time I'm in this view, I need to render the contents of the array to display to the user, after that, the user can interact with said array via the html (think of it as upvoting or downvoting stuff that's shown). Depending on the user's choice, I get a GET or POST request and need to deal with said request.
However, the way I'm implementing this seems not that elegant and I was wondering if there'd be another better way to accomplish what I'm doing.
Thank you so much!
I would suggest using a class based view

Sending form to another view django

I am building a website and I want various views that will ask the user to request a quote from our page. I want to keep the code as DRY as possible so I am writing a view quote which will receive the quote requests from various views and, if there is a validation error redirect back to the page that made the request. I managed to solve this using the super bad practice 'global variables'. I need a better solution, I would like redirecting to respective view with the current form so I can iterate through the form.errors. Here is my code:
def send_quote(request):
form = Quote(request.POST)
if form.is_valid():
# do stuff when valid
return redirect('Support:thanks', name=name or None)
quote_for = request.POST['for_what']
global session_form
session_form = form
return redirect('Main:' + quote_for) # Here I would like to send form instead of storing in global variable`
You can use the HttpResponseRedirect function, and pass as argument the page that made the request.
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
All the META data is store on a dictionary, if you want to learn more check the documentation.
https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META
If you redirect to the referrer, form.errors will be empty, as redirection is always a GET request.
I can think of two solutions to your problem:
Submit forms asynchronously using JavaScript and so populate the errors
Make all the views containing the form support POST - one way to do this would be to create a base class that inherits from FormView
The second option is a typical way of handling forms in Django - you process both POST and GET inside the same view.
After two days of searching I finally found the answer. Instead of saving form in request.session I just save request.POST and then redirect. Here is the code:
def send_quote(request):
form = Quote(request.POST)
if form.is_valid():
# do stuff when valid
return redirect('Support:thanks', name=name or None)
quote_for = request.POST['for_what']
request.session['invalid_form'] = request.POST
return redirect('Main:endview')
def endview(request):
session_form = request.session.pop('invalid_form', False)
if session_form:
form = Quote(session_form)
# render template again with invalid form ;)
Now I can repeat this with all the views I want and just change the what_for input of each form to match the respective view (Like I intended).

Django upload for processing

I'm looking for a way to upload file to django server. The thing is I'm not trying to save in I just to open it and get data for processing. I looked through some of the examples here, but I couldn't find anything that answers this. I'm probably just not looking for a correct thing please help.
I don't want to use models, just a simple website with a upload button.
Thanks!
Use a Form:
class UploadForm(forms.Form):
file = forms.FileField()
def process(self):
file = self.cleaned_data.get('file')
# do whatever you need here to process the file
# e.g. data = file.read()
In your view, call process() on your form after the user uploads the file and the form is successfully validated.
def my_view(request):
if request.method == 'POST':
form = UploadForm(files=request.FILES)
if form.is_valid():
form.process()
return ...
Depending on the size of the file and your Django settings for FILE_UPLOAD_HANDLERS, the file is discarded immediately after the view is done processing if MemoryFileUploadHandler is used. The operating system will also eventually discard the file if TemporaryFileUploadHandler is used.

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.