Django : send form in ajax with files - javascript

I know, i know, there are already some questions on this subject and believe my i've tried many many thing but still, i can't make it work.
I had a page with the form, tu upload an img with a comment (so a textarea and a file input). The thing is, i don't want to have a specific page for this form, so i have a popin with the form in a page. So i decided to do it in ajax (so the user can stay on the page and upload severals photos).
But I keep having a mistake, 'the comment field is required'. It looks like the form sent is empty. Following documentation and many (MANY) advices this is how i did it :
Form.py
class UploadPhotoForm(ModelForm):
class Meta:
model = Photo
fields = ['picture', 'comment']
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super(UploadPhotoForm, self).__init__(*args, **kwargs)
def save(self):
photo = super(UploadPhotoForm, self).save(commit=False)
artist = Artists.objects.get(user=self.request.user)
photo.artist = artist
photo.save()
return photo
views.py (the one handling the form : i changed it when i wanted to make ajax):
#login_required
#require_POST
def upload_photo_artist(request):
form = UploadPhotoForm(request.POST, request.FILES, request=request)
if form.is_valid():
form.clean()
form.save()
response = {
'code': 1,
'message': 'success',
}
return HttpResponse(
json.dumps(response),
content_type='application/json'
)
else:
response = form.errors.as_json()
return HttpResponse(
json.dumps(response),
content_type='application/json'
)
And the JS part :
$('#upload_photo').submit(function(e){
e.preventDefault();
var csrftoken = getCookie('csrftoken');
var data = new FormData($(this)[0]);
data.append('csrfmiddlewaretoken', csrftoken);
//data.append('comment', $(this).find('div.input-field').find('textarea').val());
//data.append('photo', $(this).find('div.file-field').find('input:file')[0]);
$.ajax({
url: "/photo/upload",
type: "POST",
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
data: data,
processData: false,
contentTYpe: false,
success: function(data) {
if(data['code']== 1) {
location.reload();
}
else {
alert(data);
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
});
So it looks like the formData object send is just an empty thing, but i've read the documentation and some examples and i don't see what am I doing wrong here.
You can see in comment the append() method of FormData object. I've tried to just declare a new FormData object empty and add then the fields.
In last try, i had directly the CSRFToken in the FormData object, but still, doesn't work.
If someone can help, that'd be great !

Related

Database entry not created by clicking on the accept friend request button

I am writing the view for accepting the friend request, I dont know what is happening,
i am fetching jason data to the view but i doesn't working .
i have tried all of the solutions that are on this website but they doesn't work for me
here is my Javascript
<script >
function acceptFriendRequest(friend_request_id, uiUpdateFunction){
var url = "{% url 'friend:friend-request-accept' friend_request_id=53252623623632623 %}".replace("53252623623632623", friend_request_id)
$.ajax({
type: 'GET',
dataType: "json",
url: url,
timeout: 5000,
success: function(data) {
console.log("SUCCESS", data)
if(data['response'] == "Friend request accepted."){
// ui is updated
}
else if(data['response'] != null){
alert(data['response'])
}
},
error: function(data) {
console.error("ERROR... this is the error from accept", data)
alert("Something went wrong")
},
complete: function(data){
uiUpdateFunction()
}
});
}
Here is my view
def accept_friend_request(request, *args, **kwargs):
user = request.user
payload = {}
if request.method == "GET" and user.is_authenticated:
friend_request_id = kwargs.get("friend_request_id")
# print(f"friend request id {friend_request_id}")
if friend_request_id:
friend_request = FriendRequest.objects.get(pk=friend_request_id)
# print(f"friend request object {friend_request}")
# confirm that is the correct request
if friend_request.receiver == user:
if friend_request:
# found the request. Now accept it
friend_request.accept()
payload['response'] = "Friend request accepted."
else:
payload['response'] = "Something went wrong."
else:
payload['response'] = "That is not your request to accept."
else:
payload['response'] = "Unable to accept that friend request."
else:
# should never happen
payload['response'] = "You must be authenticated to accept a friend request."
return HttpResponse(json.dumps(payload), content_type="application/json")
here is the accept()
def accept(self):
"""
Accept a friend request
update both SENDER and RECEIVER friend lists
"""
receiver_friend_list = FriendList.objects.get(username = self.receiver)
if receiver_friend_list:
receiver_friend_list.add_friend(self.sender)
sender_friend_list = FriendList.objects.get(user = self.sender)
if sender_friend_list:
sender_friend_list.add_friend(self.receiver)
self.is_active = False
self.save()
I often had the problem that I couldn't see the error message (with PHP) with the Jquery Ajax / json return. Change dataType:"json" to "text" and you may see the error message

Why an ajax call doesn't give .is_ajax()=True?

My template.html:
...
<button class="btn btn-success" onclick="save_post(event, 'publish')">Publish</button>
...
My javascript.js:
function save_post(event, action) {
event.preventDefault();#new line
var tag_string=document.getElementById('id_tags').value;
if (action=='publish' || action=='draft') {
var url_post='/blog/post/new/'
} else {
var url_post='/blog/post_edit/'
};
$.ajax({type: 'POST',
url: url_post,
data: {
tagstring: tag_string,
action: action
},
success: function (lista) {
//code
}
});
};
My views.py:
#staff_member_required
def post_new(request):
context_dict=[]
if request.method == "POST":
if request.is_ajax():
#code
...
else:
form = PostForm()
return render(request, 'blog/post_edit.html', context_dict)
My url.py:
app_name = 'blog'
urlpatterns = [
...
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit/', views.post_edit, name='post_edit'),
...
My views is called by the url (browser), then the button call a javascript function and it call (with ajax) again the same view, this time with request.method = "POST" and this works, but request.is_ajax() gives False.
For call post_edit (probabily) I need the id of the post. Where can I get it?
Should I pass it to save_post() from the template?
Edit: ignore these lines below
Also should I use preventDefault() somewhere?
Thank you
Edit: now I use preventDefault() but it gives this error:
Not Found: /blog/post_new/
[26/Jan/2018 19:07:20] "POST /blog/post_new/ HTTP/1.1" 404 10871
and ajax dosn't call the view. Edit: I solved this problem, but I continue tomorrow :)
Your Ajax code some problems and view is correct
I have attached my Code attached Image and code
$.ajax({
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
url : 'myajaxview', // the url where we want to POST
data :{
'csrfmiddlewaretoken': '{{csrf_token}}',
'text': text,
'search': search,
'email': email,
'url': url,
'telephone': telephone,
'password': password,
'number': number,
},
dataType : 'json', // what type of data do we expect back from the server
encode : true
})

How to display error messages from form with ajax using python django

I'm trying to display the error messages that I provided on my forms, but it only display the id name instead of error message.
Here's my code
Form.py
class SecurityCode(forms.Form):
sCode = forms.RegexField(regex=r'^\w+$', widget=forms.TextInput(attrs=dict(id="scode", name="scode", required=True, size=25, placeholder=" Security Code")), error_messages={ 'invalid': "This value must contain only letters, numbers and underscores." })
Views.py
def security(request):
if request.method == 'POST':
securityField = SecurityCode(request.POST)
if taxpayerField.is_valid():
return HttpResponse("success")
else:
return HttpResponse(taxpayerField.errors)
Note: I'm trying to get the error message in this views not on my html because I'm trying to alert that on my javascript. Also this is just my sample code not the original one.
You can try this:
views.py:
from django.http import JsonResponse
def security(request):
form = SecurityCode(request.POST)
if not form.is_valid():
return JsonResponse({
'success': False,
'err_code': 'invalid_form',
'err_msg': form.errors,
})
#[...] Actions if form is valid ...
return render(request, 'template.html')
javascript code:
def submit_form(){
var data = {
field1: '...',
field2: '...',
csrfmiddlewaretoken: 'csrftoken',
};
$.ajax({
url: '/submit/form/',
method: 'POST',
data: data,
dataType: 'json',
success: function (data){
if (data.success){
// Actions ...
}
else if (data.err_code === 'invalid_form'){
for(var key in data.err_msg){
console.log('[error] for ' + key + ': ' + data.err_msg[key][0]);
}
}
},
});
}
I use console.log to illustrate the recovery of the error message for each field.

django ajax call return 403 bad request

I'm trying to compile project https://github.com/kannan4k/django-carpool
please refer this project repo for this issue.
and end up with following error during ajax call.
Failed to load resource: the server responded with a status of 400 (BAD REQUEST).
I know this is because of ajax post request & CSRF tokens.
following is my setting.
1. disable "django.middleware.csrf.CsrfViewMiddleware"
2. in new_trip page I have a button (Postdata)so this button sends an ajax request.
My View:-
#login_required
def save_journey(request):
if request.is_ajax() and request.method == "POST":
try:
res = json.loads(request.body)
cords = res['cords']
cords = [[x['d'], x['e']] for x in cords]
distance = res['distance']
start_place = res['start']
end_place = res['end']
clusters = clusterize_latlngs(cords, distance)
time = datetime.datetime.strptime(res['time'], "%m/%d/%Y %H:%M")
Trip.objects.create(user=request.user, time=time, cluster=json.dumps(clusters), travel_distance=distance,
start_place=start_place, end_place=end_place)
return HttpResponse()
except:
return HttpResponseBadRequest()
else:
return HttpResponseNotAllowed(['POST'])
Ajax call (home.js)
function postData() {
radius = 0;
var url = "/save_journey/";
var dataType = 'json';
if (type == 'r') {
radius = $('#radius').val();
url = "/get_results/";
dataType = 'html';
}
var data = JSON.stringify({
cords: myroute,
time: document.getElementById('dateStart').value,
start: document.getElementById('startPlace').innerHTML,
end: document.getElementById('endPlace').innerHTML,
radius: radius,
distance: distance
});
$.ajax({
type: "POST",
url: url,
dataType: dataType,
data: data,
success: function (data) {
if (type == 'r') {
window.location.href = "/search_results/";
}
else {
window.location.href = '/trip_success/';
}
},
error: function () {
console.log('Error getting options list...')
}
});
console.log(data);
}
this code is not able to call /save_journey/ URL.
I tried many answers from stack overflow & didn't figure out what is the problem .
You should never disable csrftoken unless you're absolutely sure about what you're doing. It's an important part of the security features implemented in Django.
Here is an example of how you can use Ajax with Django with csrftoken:
You can use Ajax Post to send JSON to Django and then handle the arguments as a dict(). Here is an example:
In browser (JQuery/JavaScript):
function newModule() {
var my_data = $("#my_element").val(); // Whatever value you want to be sent.
$.ajax({
url: "{% url 'modules' %}", // Handler as defined in Django URLs.
type: "POST", // Method.
dataType: "json", // Format as JSON (Default).
data: {
path: my_data, // Dictionary key (JSON).
csrfmiddlewaretoken:
'{{ csrf_token }}' // Unique key.
},
success: function (json) {
// On success do this.
},
error: function (xhr, errmsg, err) {
// On failure do this.
}
});
In server engine (Python):
def handle(request):
# Post request containing the key.
if request.method == 'POST' and 'my_data' in request.POST.keys():
# Retrieving the value.
my_data = request.POST['my_data']
# ...
Hope this helps.

how to upload file on django server using javascript/jQuery and ajax

After having spent hours, I need help to match the javascript code to the django codes.
I am using the "minimal-django-file-upload-example" version django 1.8 from the git https://github.com/axelpale/minimal-django-file-upload-example.
In standalone, it works very well.
Now i try to upload file from javascript and i do not succeed to make it works.
Javascript Code
function UploadBlob(zip)
{
var ZipFileBlob = zip.generate({type:"blob"});
var fd = new FormData();
fd.append('data', ZipFileBlob);
fd.append('fname', 'ZipOfImage.zip');
fd.append('enctype','multipart/form-
$.ajaxSetup({
type: 'POST',
url: 'http://127.0.0.1:8000/myapp/list/',
enctype: "multipart/form-data",
headers: { "X-CSRFToken": getCookie("csrftoken") }
});
$.ajax({
data: fd,
processData: false,
contentType: false
}).done(function(data) {console.log(data);});
}
Django code
in forms.py
class DocumentForm(forms.
docfile = forms.FileField(label='Select a file')
in views.py
def list(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile = request.FILES['docfile'])
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('myproject.myapp.views.list'))
else:
print "invalid form"
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render_to_response(
'list.html',
{'documents': documents, 'form': form},
context_instance=RequestContext(request)
)
The code run up to the request.method == 'POST'. After, i do not know if i should add field to the ajax requests (and which ones) or if there is a more suitable form in django or do something else.
Please help!

Categories