How to access request.FILES in my views? - python

Trying to upload an image to a model image field with AJAX. Here's my code:
js
$('input#id_banner_image').on('change', function(e) {
$.ajax({
type: 'POST',
url: '/change_banner_image/',
data: {
image: URL.createObjectURL(e.target.files[0]),
csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val()
}
})
});
views
def change_banner_image(request):
if request.is_ajax():
print(request.FILES) #prints <MultiValueDict: {}>
for i in request.FILES:
print(i) #prints nothing
image = request.FILES['id_banner_image'].name #this is wrong
profile = get_object_or_404(Profile, user=request.user)
profile.image = image
profile.save()
return HttpResponse()
How do I correctly grab the image in my views? I know that's the bit that's wrong.

Related

Unable to render a template after using fetch in django

I have the following requirement:
Send data to backend using fetch()
receive the data in a view and render another template ( route to a different view)
The following is my code snippet:
JS:
fetch("/addpost", {
method: "POST",
body: JSON.stringify({ value: selecteddict }),
headers: {
"Content-type": "application/json;",
},
})
.then((res) => {
return res.text();
})
.then((text) => {
console.log(text);
});
// the data is being sent successfully
Django View1:
#csrf_exempt
def addpost(request):
if request.method == 'POST':
song = json.loads(request.body.decode('utf-8'))['value']
print(song)
# I want to redirect to another view called createpost that renders a new page
return JsonResponse({'status':201})
return render(request, 'addpost.html')
Django createpost view:
def createpost(request):
return render(request, 'createpost.html')
The view createpost is working fine when given the required path but it is not rendering when it's redirected from addpost
Please suggest a solution to this.
Your addpost view returns as JsonResponse in case of a POST request. If you want to redirect somewhere you need to use redirect() instead of JsonResponse()

Remote image upload performs different than development server

My local development and live development server have the exact same code and database (all static/media files upload to s3 storage).
I have a Post model with an image field. My Post has an image upload field which uploads via AJAX to my s3 storage. In both my local and live server, the image successfully uploads and the url of that image in my s3 bucket is saved. So when I submit the Post in my local server, it doesn't upload again, I just point to the URL when I render the image.
However, my remote server doesn't do this. After I have uploaded the image via AJAX, when I submit the Post form, it then submits the image again (it shows the upload progression on my browser - 3%, 5%, 10% etc...).
Any idea why this happens? My code is here:
models
class Post(models.Model):
image = models.FileField(null=True, blank=True)
views
def post(request):
if request.user.is_authenticated():
form_post = PostForm(request.POST or None, request.FILES or None)
if form_post.is_valid():
instance = form_post.save(commit=False)
instance.user = request.user
...
if instance.image:
instance.imageURL = "https://s3.us-east-2.amazonaws.com/my-bucket/media/%s" % filename
instance.image = None #this prevents re-upload upon form submission
instance.save()
return HttpResponseRedirect('/')
else:
form_post = PostForm()
context = {
'form_post': form_post,
}
return render(request, 'post/post.html', context)
else:
return HttpResponseRedirect("/accounts/signup/")
ajax view
def upload_image(request):
random_filename = request.POST.get('random_filename')
if request.is_ajax():
if request.FILES:
img = request.FILES.get('image')
session = boto3.Session(
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
)
s3 = session.resource('s3')
s3.Bucket('my-bucket').put_object(Key='media/%s' % random_filename, Body=img)
return HttpResponse()
else:
return HttpResponse()
template
<input id="id_image" type="file" name="image" />
JS
$('input#id_image').on('change', function(e) {
var file = $('input[type=file]')[0].files[0];
var formData = new FormData();
$('.add_file_div h3').hide();
$('.add_file_label').css({
'border-radius': '5px',
'box-shadow': '5px',
});
var imagePath = URL.createObjectURL(e.target.files[0]);
var random_filename = random_string();
formData.append('image', file);
formData.append('csrfmiddlewaretoken', $("input[name='csrfmiddlewaretoken']").val());
formData.append('random_filename', random_filename);
$.ajax({
url: '/upload_image/',
data: formData,
type: 'POST',
contentType: false,
processData: false,
success: function(){
console.log('SUCCESSFULLY UPLOADED');
$('.add_file_label').css('opacity', '1');
$('.add_file_label').css('background', 'url(' + imagePath + ') scroll no-repeat center/cover');
$('.loading_spinner').css('visibility', 'hidden');
}
});
$('.add_file_label').css('background', 'url(' + imagePath + ') scroll no-repeat center/cover');
$('.add_file_label').css('opacity', '0.4');
$('.loading_spinner').css('visibility', 'visible');
console.log(imagePath);
$('.add_file_label').append('<input class="temp_s3_url" type="hidden" name="temp_s3_url">');
$('.temp_s3_url').val(random_filename);
$('input#id_imageURL').hide();
$('#delete_preview_image').show();
});
PS: My nginx has client_max_body_size 200m; so that's not the problem
I think the same issue may be happening locally also. But when you are local the speed is fast enough for you to not see a upload progress bar. The thing is that you should clear your file field when you have had a success in the ajax upload
how to reset <input type = "file">
so inside
success: function(){
console.log('SUCCESSFULLY UPLOADED');
$('.add_file_label').css('opacity', '1');
$('.add_file_label').css('background', 'url(' + imagePath + ') scroll no-repeat center/cover');
$('.loading_spinner').css('visibility', 'hidden');
}
You would reset the file element to make it a blank value, else it will get submitted with the form.
Another option could be to just give the file input field a id and not a name. If there is no name attached to a input element it doesn't get submitted with a form

Unable to receive json response from Django view to template?

I am trying to send a json response from django view to template but when I try to console.log the response in my ajax, I am getting nothing. What could i be doing wrong ? I am trying to pass the result data from views to my ajax success function. I also noticed something strange that when I mention the datatype = json in my ajax then I dont receive any response in the success function but when I remove the dataType = json then I get the entire html of my template in my success function as a response. Why is that ??
views.py
class ChangePassword(View):
def post(self, request, *args, **kwargs):
form = PasswordChangeForm(request.POST)
#current_password = json.loads(get_value.current_password)
#print ('current password',get_value['current_password'])
if form.is_valid():
print("valid form")
user = CustomUser.objects.get(email=request.user.email)
current_password = form.cleaned_data['current_password']
print('current_password',current_password)
new_password = form.cleaned_data['new_password']
print('newpassword',new_password)
if user.check_password(current_password):
print('entered')
update_session_auth_hash(self.request, self.request.user) # Important!
user.set_password(new_password)
user.save()
result = {'success': "Succefully reset your password"};
result = json.dumps(result)
print ('result',result)
return render(request, 'change_password.html',context={'result': result})
else:
return render(request, 'change_password.html', {'error': "We were unable to match you old password"
" with the one we have. <br>"
"Please ensure you are entering your correct password"
"then try again."})
else:
print("not valid")
return render(request, 'change_password.html', {'form':form})
def get(self, request, *args, **kwargs):
return render(request, 'change_password.html', {})
template
function changePassword() {
csrfSetUP()
new_pass = document.getElementById('new_pass')
cur_pass = document.getElementById('current_pass')
if (validpassword(new_pass) && cur_pass!= "") {
var cpass = $('#current_password').val();
var npass = $('#new_pass').val();
var data = {current_password:cpass,new_password:npass}
$.ajax({
url: '/account/change_password/',
type: 'post',
data: data,
dataType: "json",
success: function(json) {
console.log(json)
}
});
} else {
$('#change_password').submit()
}
}
When you are working with AJAX you have to use JSONResponse() instead of render()
from django.http import JsonResponse
return JsonResponse({'foo':'bar'})
If you need to have generated some HTML with that JSON - it is even better to use render_to_string method and return a html string to your AJAX, smth like that:
html = render_to_string('ajax/product_details.html', {"most_visited": most_visited_prods})
return HttpResponse(html)
NOTE: When using render_to_string remember to delete dataType: "json" from your AJAX, cuz u return not JSON, but a string.
P.S. Under this question there are plenty of examples how this can be done, but look at newer ones.

Django: How to Like an Object with Ajax

Here's my View,
class ObjLike(RedirectView):
def get_redirect_url(self, *args, **kwargs):
id = self.kwargs.get('id')
obj = get_object_or_404(Data, id=id)
user = self.request.user
if user.is_authenticated():
if user in obj.likes.all():
obj.likes.remove(user)
else:
obj.likes.add(user)
So after this view how can I redirect user to the same page?
I used "return redirect(request.META['HTTP_REFERER'])" but it gives an error "name 'request' is not defined"
I can't use the get absolute URL method, i'm using this view at several places.
So, how can I do that?
to like an object with ajax calls do this
first in html we want to make a like button:
<button id="like">Like!</button>
the add a script that contain the ajax:
<script>
$(document).ready(function() {
$("#like").click(function(event){
$.ajax({
type:"POST",
url:"{% url 'like' Obj.id %}",
success: function(data){
confirm("liked")
}
});
return false;
});
});
</script>
the we add the like url to the urlpatterns list:
url(r'like/obj/(?P<pk>[0-9]+)/', views.like, name="like"),
adding the view :
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def like(request, pk)
obj = Obj.objects.get(id=pk)
obj.likes += 1
obj.save()
return HttpResponse("liked")
Note: you can customize the like view to check if user liked already

Django returns invalid ajax response

I have a ajax call in my django template file as:
$(document).ready(function () {
$("button#wdsubmit").click(function(){
$.ajax({
type: "post",
url: "/audit/addwd/",
data: $('form.wddetails').serialize(),
dataType: "json",
success: function(msg){
alert(msg);
alert('Added Successfully');
$("#newwd").modal('hide'); //hide popup
},
error: function(msg){
alert(msg.success);
}
});
});
});
Form:
class WDForm(ModelForm):
class Meta:
model = WDModel
fields = '__all__'
and view in django is :
def addwd(request):
if request.method == 'POST':
updated_request = request.POST.copy()
updated_request.update({'updated_by': request.user.username})
form = WDForm(updated_request)
if form.is_valid():
form.save()
response = simplejson.dumps({'success': True})
return HttpResponse(response, content_type="application/json", mimetype='application/json')
else:
response = simplejson.dumps({'error': True})
return HttpResponse(response , content_type="application/json")
Whenever I make a Ajax call it always returns error even though I have sent Success(Means the form is valid and data is successfully pushed to database).
I also tried to send response={'success':True} doesn't work.
Please help me to solve this issue.
Environment Details:
Python verion: 3.4
Django :1.7
Windows OS 8
I doubt on this line " response = simplejson.dumps({'success': success})
"
you can try JsonResponse objects.
from django.http import JsonResponse
return JsonResponse({'foo':'bar'})

Categories

Resources