Raise MultiValueDictKeyError by request.FILES to get base64 image data - django

Actually i need to get base64 image data generated by croppie javascript library. The image data look like below.
data:image/png;base64,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
Here is my HTML
<form action="{% url 'profile' %}" enctype="multipart/form-data" method="post" class="pic-upload-form" id="form">{% csrf_token %}
<div class="custom-file">
{% bootstrap_form form %}
</div>
<!-- Croppie area -->
<div id="upload-demo"></div>
<input type="hidden" id="image-data" name="imagebase64">
<button type="button" class="btn btn-outline-info btn-custom upload-result">save</button>
</form>
The last portion of my js where i bind the image data to a hidden input.
$('.upload-result').on('click', function (ev) {
$uploadCrop.croppie('result', {
type: 'base64',
size: 'viewport'
}).then(function (src) {
console.log(src);
// bind the image data to the hidden inpu id image-data
$('#image-data').attr('src', src);
$('#form').submit();
});
});
And here is my view
def user_profile_view(request):
'''Handle the image of the user.'''
if request.method == 'POST':
form = UploadPicForm(request.POST, request.FILES)
if form.is_valid():
profile = form.save(commit=False)
# get the base64 image data
profile.image = request.FILES['imagebase64']
profile.save()
messages.success(request, 'your pic updated successfully.')
return HttpResponseRedirect(reverse('learning_path_tracker:home'))
else:
# form's user field populated by current user
form = UploadPicForm(initial={'user': request.user})
return render(request, 'users/uploadpic.html', {'form': form})
I think the image data is not a string that's why request.FILES raise error. But how can i solve this, thanks in advance.

request.FILES only contain the files uploaded using input type="file". Whereas you're sending the image data as a base64 using type="hidden" which sends data as string, not as file.
So, the image should be present in request.POST instead of request.FILES.
Do this:
profile.image = request.POST['imagebase64']
As a side note, instead of accessing keys directly from a dictionary, you should use the dict's get() method because it let's you provide a default value if the requested key is not present in the dictionary.
profile.image = request.POST.get('imagebase64', "default value")

Related

Django saving data from html field to database

I am new to Django, I am trying to take input from user using html generated text field and not use django forms.
<form action="" method="post">
{ % csrf_token % }
<label for="name">Enter name: </label>
<input id="namefield" type="text" name="name_field" value="Default name">
<input type="submit" value="OK">
</form>
I want to save the name to my database, without creating a django form and taking in data from the form and saving it in the database via views.py file.
In your view:
If request.method == 'POST' :
name = request.POST['field_name']
#now you can save them into related model
MyModel.objects.create(username=name,other fields goes here)
You must create in the views.py file a method in which the templates and the logic of it, an example can be the following
#csrf_exempt
def home(request):
if request.method == 'POST':
var1 = request.POST.get('var1')
var2 = request.POST.get('var2')
var3 = request.POST.get('var3')
#Save to the database here
return render_to_response(
'home.html',
{'message': 'Update Success', }
)
else:
return render_to_response(
'home.html',
{}
)

Django form error:local variable 'context' referenced before assignment

I'm collecting data from form, processing data(right now I'm not) and displaying the result on the same HTML page from where the user submits the form.
Here is my views.py file:
def index(request):
template = 'predictor/index.html'
if request.method =='POST':
form = EvalForm(request.POST)
if form.is_valid():
text ='thank you for submitting form'
else:
text='something wrong.'
context: {
'text':text,
}
return render(request,template,context)
else:
form = EvalForm()
return render(request,template)
Here is my index.html file
<form method="POST" action="{% url 'predictor' %}">
{% csrf_token %}
//all input fields including submit button here
</form>
<div class="result">
{{ text }}
</div>
All other things like urls are configured properly.
What I'm doing wrong here?
You have typo in your code.
Should be context = {'text':text,} instead of context: {'text':text,}.

Invalid form when uploading a file

I am trying a basic example in uploading a file with django.
I tried the code from the django documentaion but I keep getting invalid form. And when I don't test the validation of the form and try to handle the file directly, I get:
MultiValueDictKeyError at /neurons/nblast
"
'file'"
P.S:
Previously, I had used a model with a FileField and set the (upload_to), but in my current case I don't need to use the model, I only need to let the user uploads his files.
This is my code:
Template
<body>
<form action="" method="post">
{{ form }}
<br>
<button class="btn btn-success" name="btn_upload">
<span class="glyphicon glyphicon-upload"></span>
<b>Upload</b>
</button>
{% csrf_token %}
</form>
</body>
Views
def test(request):
if request.method == GET:
form = UploadFileForm()
if request.method == POST:
if 'btn_upload' in request.POST:
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
else:
print 'Not Valid'
form = UploadFileForm()
return render_to_response('test.html',
{'form': form},
context_instance=RequestContext(request))
Forms:
class UploadFileForm(forms.Form):
file = forms.FileField()
Thank you very much
Have you tried looking at The Django 'File Uploads' docs , especially the enctype="multipart/form-data" attribute?
u missed this one enctype="multipart/form-data"

Django form returns form.is_valid False

This must be kind of basic issue but I am very new in Djnago and trying to learn how the forms work. I have looked in different sites and forums but I haven't managed to understand what I am doing wrong.
This is my form:
class UploadCSVForm(forms.Form):
csv_file = forms.FileField()
Its a very simple form used in order to upload a CSV file.
This is what I have in my view:
def layer_create(request, template='layers/layer_create.html'):
if request.method == 'POST':
form = UploadCSVForm(request.POST, request.FILES)
#print form.is_bound # THIS PRINTS TRUE
#print (request.FILES['csv']) # THIS PRINTS THE FILE IN THE MEMORY
if form.is_valid():
print ("valid")
else:
print ("not valid")
out = {'success': False}
return HttpResponse('test site')
And this is the form in my Template:
<form id="file-uploader" method="post" enctype="multipart/form-data" action="{% url "layer_create" %}">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
<input type="file" id="file-input" name="csv" />
<button type="submit" id="upload-button" class="btn btn-danger">Upload</button>
</form>
Using the function is_bound I see that there are actual data bound on the form.
And when I print: request.FILES['csv'] I can see the name of the file uploaded in the Memory.
But I still get form.is_valid = False without ant errors or warnings.
You've named the field in the template csv, but the form is expecting it to be called csv_file.
Generally you should let Django output the fields in the template, which will avoid issues like this. (It will also normally prepopulate the fields when redisplaying them after errors, although this doesn't happen for file fields for browser security reasons.)
{{ form.csv_file }}

Trying to use django and dropzone/

I'm trying to use dropzone.js with django.
I'm following the somewhat dated guide here (https://amatellanes.wordpress.com/2013/11/05/dropzonejs-django-how-to-build-a-file-upload-form/)
I strongly suspect My view is at issue.
def test(request):
print "test view has been called"
if request.method == 'POST':
print "test request method is POST"
form = UploadFileForm(request.POST, request.FILES)
print request
print request.FILES
if form.is_valid():
new_file = AttachedFiles(attachedfile=request.FILES['file'])
new_file.save()
id = new_file.pk
print id
print "test form valid"
return HttpResponse(json.dumps({'id': id}), content_type="application/json")
print "test form not valid"
else:
form = UploadFileForm()
data = {'form': form}
return render_to_response('mediamanager/test.html', data, context_instance=RequestContext(request))
I've tested submitting to it with the dropzone code
<!-- IMPORTANT enctype attribute! -->
<form id="my_dropzone" class="dropzone" action="/mediamanager/test/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<button id="submit-all">
Submit all files
</button>
</form>
<script src="{% static 'dropzone/js/dropzone.js' %}"></script>
<script type="text/javascript">
Dropzone.options.myDropzone = {
// Prevents Dropzone from uploading dropped files immediately
autoProcessQueue : true,
init : function() {
var submitButton = document.querySelector("#submit-all")
myDropzone = this;
submitButton.addEventListener("click", function() {
myDropzone.processQueue();
// Tell Dropzone to process all queued files.
});
// You might want to show the submit button only when
// files are dropped here:
this.on("addedfile", function() {
// Show submit button here and/or inform user to click it.
console.log("blah")
});
}
};
</script>
and a basic form
<form action="{% url "test" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="file" />
<input type="submit" value="Submit">
</form>
And the form is never valid.
I'm using a modelform as suggested
class UploadFileForm(forms.ModelForm):
class Meta:
model = AttachedFiles
You can handle Dropzone posts like any other multipart form post.
Here's how I proceed:
#login_required
#usertype_required
def upload_picture(request, uid=None):
"""
Photo upload / dropzone handler
:param request:
:param uid: Optional picture UID when re-uploading a file.
:return:
"""
form = PhotoUploadForm(request.POST, request.FILES or None)
if form.is_valid():
pic = request.FILES['file']
# [...] Process whatever you do with that file there. I resize it, create thumbnails, etc.
# Get an instance of picture model (defined below)
picture = ...
picture.file = pic
picture.save()
return HttpResponse('Image upload succeeded.')
return HttpResponseBadRequest("Image upload form not valid.")
The form is dead simple
class PhotoUploadForm(forms.Form):
# Keep name to 'file' because that's what Dropzone is using
file = forms.ImageField(required=True)
In your model you need the upload_to set:
class Picture(models.Model):
[...]
# Original
file = models.ImageField(upload_to=get_upload_path)
And here's my upload path builder, but you can put anything
def get_upload_path(instance, filename):
""" creates unique-Path & filename for upload """
ext = filename.split('.')[-1]
filename = "%s.%s" % (instance.p_uid, ext)
d = datetime.date.today()
username = instance.author.username
#Create the directory structure
return os.path.join(
'userpics', username, d.strftime('%Y'), d.strftime('%m'), filename
)
Don't forget the csrf_token in the html form itself (I'm using an angularJS directive on top of it so will be different for you)
<form action="{% url 'upload_picture' %}" class="dropzone" drop-zone>
{% csrf_token %}
<div class="fallback">
<h3>Your browser is not supported.</h3>
<strong>
Click here for instructions on how to update it.
</strong>
<p>You can still try to upload your pictures through this form: </p>
<p>
<input name="file" type="file" multiple />
<input type="submit" value="Upload" />
</p>
</div>
</form>
I got dropzone js working by modifying the bootstrap example (I am using bootstrap) here: http://www.dropzonejs.com/bootstrap.html
I do not use any forms. I got a view handling the in coming ajax posts from dropzone. Here is the gist of my view code:
class AjaxUploadView(View):
"""
View for uploading via AJAX.
"""
def post_ajax(self, request, *args, **kwargs):
uploaded_file = request.FILES['file']
# Do stuff with file
# Return appropriate response
Hope it helps.