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.
Related
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.
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.
I have a Django page with a form. I have some view code which deals with the form as normal but prepopulates the form with initial data from the a user's session if available. This is so that when a user returns to this form they see previously selected options (yes, the form is quite extensive).
My views,py:
def myView(request):
...
form = ProjectInfoForm(request.POST or None)
if form.is_valid():
# process form, including a redirect
...
# if there is form data in the session, let's use that
# to initaliaze our from with data
if key in request.session:
form = ProjectInfoForm(
initial={
'model': request.session.get('model'),
...
}
)
return render_to_response(template_name, {
...
}, RequestContext(request))
Problem is: if I load the session data then the page does not display any error messages. The form does fail validation, I am just not getting the any output. Is there some conflict here with initial?
Any help would be much appreciated.
Well, from that snippet, if the session data is found then you completely re-initialize the form: the original, validated instance, which contained the POST data and any errors, has now been disposed. Presumably you would want to only enter that second if if the request is not a POST.
I've seen Django's samples and I can see they have decent error handling. However I want to see if there is yet a better approach, a general pattern to handle form validation errors in Django. This is the sample I found here:
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render_to_response('contact.html', {
'form': form,
})
In particular, I was wondering:
How can the view in "/thanks/" be sure that the form was validated? Are there any common ways to pass the successful validation of the form to the next view? Or do I need to do something manually such as setting a flag in request's session?
How can one write this code in a way that when form is NOT valid and the page is shown with errors upon submission, if user refreshes the browser it wouldn't ask the user if they want to POST data again?
EDIT: With regards to #1 I am referring to cases like user manually entering the '/thanks/' url or going back and forth through history pages and accidentally openning it without any form being validated. (Do we still show the "thanks" page? or we need to somehow re-validate why we are in thanks view).
The view can be sure that the form is validated because it will only be called if the form is valid...
If the page is generated through a post request the browser will always ask you that when hitting refresh... I guess the only way to avoid this would be redirecting to another page!
How can the view in "/thanks/" be sure that the form was validated?
form.is_valid() should thoroughly check any field or - if necessary - any combination, cornercase, etc. That's basically it. The views knows, the form was valid if it renders. There is no need to include redundant information in the session.
How can one write this code in a way that when form is NOT valid and the page is shown with errors upon submission, if user refreshes the browser it wouldn't ask the user if they want to POST data again?
I am not sure what the point would be. The form contains errors and the user may correct them or leave. To render a page that would not ask for form resubmission, one could use a redirect, just as in the valid case. The error markup would have to be done manually in that case.
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!