I'm newer in Django and some time ago I've totally stuck on problems with my requests. I'm trying to do POST from Django form. I do that with json and AJAX
Here is my code
form.py
class PostForm(forms.ModelForm):
class Meta:
model = Message
fields = ['message_text']
widgets = {
'message_text': forms.TextInput(
attrs={'id': 'message_text', 'required': True,
'placeholder': 'new message...', }),}
views.py
def index(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
form.cleaned_data
message_t = request.POST.get('message_text')
response_data = {}
new_mess = Message(message_text = message_t,
post_time = message_t.created,
username="second")
new_mess.save()
response_data['result'] = message_t
else:
response_data['result'] = 'nothing...'
else:
form = PostForm()
template = loader.get_template('chat/index.html')
context = RequestContext(request, {
'form': form, })
return HttpResponse(template.render(context))
(In another variant of views.py I tried to separate POST request handling to another function, but it doesn't work as well)
html:
<form method="POST" id="post-form">
<td class="col-lg-6"><div class="fieldWrapper" id="the_post"
class="form-control" type="text">
{{ form.message_text }}
</div></td>
<td class="col-lg-6"> <input type="submit" value="Post"
class="btn btn-success" name = "Post"></td>
</form>
js:
$(function() {
$('#post-form').on('submit', function(event){
event.preventDefault();
console.log("form submitted!") // sanity check
create_post();
});
function create_post() {
console.log("create post is working!") // sanity check
$.ajax({
url : "/chat/new_message/", // the endpoint
type : "POST", // http method
data : { the_post : $('#post-form').val() },
success : function(json) {
$('#post-form').val(''); // remove the value from the input
console.log(json); // log the returned json to the console
console.log("success");
},
error : function(xhr,errmsg,err) {
...
}
});
};
});
In the result my POST is successful, no error appears, but no record in the base created too.
Note: Also I've excluded csrf everywere
Can someone help me to figure out what's wrong?
The form is not valid. It can never be valid, because you are sending a JSON dictionary with the form data inside the key "the_post", but you haven't told the view to look there.
And the view can't report back the status of the form, because you construct a response - "response_data" - and then ignore it.
Finally, your view does not send back JSON anyway - it sends back the rendered template, as if it were a normal non-Ajax view - so the receiving JS has no idea what to do with it.
I've found the fix for my POST.
The main problem was in json body, I was using wrong value name, it has to be:
data : { the_post : $('#message_text').val() },
Now request is not empty.
Related
html
<div>
{{ productform.vendorid|as_crispy_field }}<a id="vendor_id_search" class="btn btn-info">search</a></br>
<div style="display:none;" id="show_vendorname">hjkh</div><br>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$("#vendor_id_search").click(function (event) {
event.preventDefault();
var vendor_id = $("#id_vendorid").val();
$.ajax({
url: '/ajax/find_vendorname/',
method: 'GET',
data: {
'vendor_id': vendor_id
},
dataType: 'json',
success: function (data) {
$("#show_vendorname").show(data)
}
});
});
views.py
#vendor_name_find_ajax
def find_vendorname(request):
if request.is_ajax():
vendorid = request.GET.get('vendor_id', None)
username = CustomUser.objects.filter(first_name=vendorid)
return username
I want to display the related name from the database table for that vendorid after the user typed the vendorid field and once clicked the button, the related name should be displayed on that particular div. Here, I have made a mistake and don't know to get that value.
$("#show_vendorname").show(data) unhide the div, but don't set in the data.
You need set the data before with $.html()
$("#show_vendorname").html(data).show()
EDIT:
Besides, your view needs to return a HttpResponse:
from django.http import HttpResponse
def find_vendorname(request):
if request.is_ajax():
vendorid = request.GET.get('vendor_id', None)
username = CustomUser.objects.filter(first_name=vendorid)
return HttpResponse(username)
First of all : I already checked all the related answers and questions .... they didn't help me
so I am trying to create ajax based like button with multiple users and multiple objects or posts i tried a lot but none of them works but i steel have the base
models.py:
class BlogPost(models.Model):
#some fields
class Like (models.Model):
user = models.ForeignKey(User)
post = models.ForeignKey(BlogPost)
views.py
from .models import Like
def PostLikeToggle(request):
#here i want to capture the request check if the user liked the post or
# no by sending user.username and post.title to the endpoint like.html
#and then update his status
return render(request, 'like.html')
urls.py
from plateform import views as plateform
urlpatterns = [
#other urls
url(r'^like/', plateform.PostLikeToggle, name='PostLikeToggle'),]
like.html
{% if liked == 'false' %}
false
{% elif liked == 'true' %}
true
{% endif %}
blogpost.html
#ajax
$('.thumb').click(function () {
$.ajax({
type: 'POST',
url: '/like/',
data: {
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
},
success: LikePost,
dataType: 'html'
});
function LikePost(data, jqXHR) {
console.log(data)
}
});
UPDATE
I tried to figure it out so I added some things
models:
class BlogPost(models.Model):
#some fields
liked = models.ManyToManyField(User, related_name='PostLikeToggle')
#REMOVED class Like (models.Model)
views:
def PostLikeToggle(request):
user = request.user
if request.method == 'POST':
post_id = request.POST['post_id']
post = get_object_or_404(posts, id=post_id)
_liked = user in post.liked.all()
if _liked :
post.liked.remove(user)
else:
post.liked.add(user)
return JsonResponse({'liked':_liked})
So am I on the right way ??
okey I will just post my answer .... it was easy trick but i was little bit stingy ...
In the models file i added ManytoMany field with the relation of users ( many users + many posts)
class BlogPost(models.Model):
#more fields
liked = models.ManyToManyField(User, related_name='PostLikeToggle')
in the views i created the view which it will accept the request from the blogpost views and check if user already liked the post or no ( add the user to the liked field if liked return true remove it if .... )
def PostLikeToggle(request):
user = request.user
if request.method == 'POST':
post_id = request.POST['post_id']
post = get_object_or_404(posts, id=post_id)
_liked = user in post.liked.all()
if _liked :
post.liked.remove(user)
else:
post.liked.add(user)
return JsonResponse({'liked':_liked})
this views is associated with url where we will get the response :
url(r'^like/', plateform.PostLikeToggle, name='PostLikeToggle')
and in your blog post template you will need to link Jquery and add this Ajax function
(don't forget to customize it with your own variable class , url ... )
$('.thumb').click(function () {
$.ajax({
type: 'POST',
url: {% url 'PostLikeToggle' %},
data: {
'post_id': {{ post_slug.id }},
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
},
success: LikePost,
dataType: 'html'
});
function LikePost(data, jqXHR) {
var data = $.parseJSON(data)
if (data['liked']) {
$('.thumb').removeClass("fas fa-thumbs-up").addClass('far fa-thumbs-up')
}
else
{
$('.thumb').removeClass("far fa-thumbs-up").addClass('fas fa-thumbs-up')
}
}
});
this worked for this time if there is any exception or you have better way just post it and i will mark it
NOTICE : you have to check if the user if authenticated in the template to hide the like button or redirect him to login ....
I am going to add a button in my page to upload file.User clicks this button and choose file from computer, the page will upload file to the server and show a message like 'Upload successfully' to the user.
I have noticed that Django has Filefield in model and we can define a class FileForm so that we can use form = UploadFileForm(request.POST, request.FILES) and form.save() to upload.
However,as I want to refresh part of the page after upload, it comes to me to use ajax to send data.Furthermore,in order to use request.FILES which requires that request has the attribute enctype="multipart/form-data", I think maybe we can use FormData() in ajax.
html:
<div>
<input type="file" name="" id="ul_input">
<input type="hidden" name="local_id" id="get-local-id" value="{{ record.local_id }}"/>
</div>
Javascript:
// grab your file object from a file input
$('#ul_input').change(function () {
var formData = new FormData();
formData.append("ul_file", this.files[0]);
formData.append("filename", this.files[0].name);
formData.append("local_id", $('#get-local-id').val());
$.ajax({
url: 'uploadfile',
type: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: "json",
beforeSend: function () {
console.log("loading...please wait");
},
success: function (responseStr) {
if (responseStr.status === 0) {
alert('upload successfully');
} else {
alert("upload fail");
}
},
error: function (responseStr) {
console.log("error");
}
});
});
views.py
def order_upload(request):
status = 1
if request.is_ajax():
local_id = request.POST.get('local_id')
post = DetailList.objects.get(local_id=local_id)
post.order_dir = request.FILES['ul_file']
post.save()
status = 0
return HttpResponse(json.dumps({'status': status}), content_type='application/json')
models.py
def file_directory_path(instance, filename):
return 'file_list/{0}{1}/{2}'.format(instance.upload_date.strftime('%Y'),
instance.upload_date.strftime('%m'),
filename)
class DetailList(models.Model):
local_id = models.IntegerField(...)
start_date = models.DateField(...)
order_dir = models.FileField(upload_to=file_directory_path, blank=True, null=True)
Dont forget to set MEDIA_ROOT = '/media/' in settings.py
I try to upload a file 'test.docx'.Now it seems that I have alreay uploaded file to media/file_list/201807/test.docx.I also check order_dirin table,it has already become file_list/201807/test.docx.And I got the alert says 'upload successfully'.
However,I can't find my 'test.docx' in directory 'media/file_list/201807/test.docx'.
Where is the file I uploaded? Can anyone help?
I'm working on a project in which I'm using Python(3.6) & Django(1.10) and I need to implement Paypal payment method in this project. I have decided to use the official Python SDK from Paypal instead of other third-party packages.It's not only the csrf problem but it also how we can render a custom form for paypal checkout button.
Here's wwhat Ihave tried.
According to the docs as Here.
Here's my template:
<form class="form">
{% csrf_token %}
<div id="paypal-button"></div>
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
<script>
var CREATE_PAYMENT_URL = '{% url 'users:payment' %}';
var EXECUTE_PAYMENT_URL = 'https://my-store.com/paypal/execute-payment';
paypal.Button.render({
env: 'sandbox', // Or 'production'
commit: true, // Show a 'Pay Now' button
payment: function () {
return paypal.request.post(CREATE_PAYMENT_URL).then(function (data) {
return data.paymentID;
});
},
onAuthorize: function (data) {
return paypal.request.post(EXECUTE_PAYMENT_URL, {
paymentID: data.paymentID,
payerID: data.payerID}).then(function () {
// The payment is complete!
// You can now show a confirmation message to the customer
});
}
}, '#paypal-button');
</script>
</form>
From urls.py:
url('^payment/$', views.PaymentProcess.as_view(), name='payment'),
From views.py:
class PaymentProcess(LoginRequiredMixin, generic.DetailView):
def post(self, request, *args, **kwargs):
mydict = {
'paymentID': 'PAYMENTID',
}
print('Getting payment request')
return json.dumps(mydict)
When Paypal submits a post request to /payment it returns 403 Forbidden error due to csrf_token. How can I pass the csrf_token with this request.
Any resource or tutorial will be really appreciated.
It seems you can add custom headers to your post request : https://github.com/paypal/PayPal-Python-SDK/blob/master/paypalrestsdk/api.py#L270
Given that you just have to add you csrf token to the headers : https://docs.djangoproject.com/en/2.0/ref/csrf/#setting-the-token-on-the-ajax-request
And your server should give you access
I am trying to call my view from django template via an Ajax call.
I want the form object in response from view such that I can render this form via jquery in a div element.
Is it possible ? How?
This is what i tried:
home.html
function get_edit_form(button, id)
{
$.ajax({
url: "/manage/licenses/{{mls_signup_code}}/{{agent_id}}/" + id + "/",
type: "get",
data: {id: id},
success: function(response) {
console.log(response);
$("#formdiv").html({{ response.as_p }});
}
})
}
Views.py
elif request.method == "GET":
owned_license_id = request.GET.get('id', '')
form = OwnedLicenseForm(owned_license_id)
return form
I see what you are trying to do, but you cannot render the html form this way:
$("#formdiv").html({{ response.as_p }});
I think you are confusing server side rendering (Django templates) with client side rendering. Server side rendering happens when your server is processing the request, it cannot render objects produced by javascript running in the browser.
Because response is a javascript object, obtained by jquery sending an Ajax request to your url. At this time, the page has already been rendered by Django's template engine, and sent to the browser. There is no way for Django template to even be aware of this response.
I understand you want to use the as_p() method to render the form, you can do it like this:
function get_edit_form(button, id)
{
$.ajax({
url: "/manage/licenses/{{mls_signup_code}}/{{agent_id}}/" + id + "/",
type: "get",
data: {id: id},
success: function(response) {
console.log(response);
// response is form in html format
$("#formdiv").html(response);
}
})
}
# Views.py
elif request.method == "GET":
owned_license_id = request.GET.get('id', '')
form = OwnedLicenseForm(owned_license_id)
return HttpResponse(form.as_p()) # return a html str
You can accomplish this with a combination of Django and JQuery.
Step 1: Create an ultra simple form_from_ajax.html Template
The template can be as simple as {{form.as_p}}. The point is to not inherit your base template. You're simply using this form_from_ajax.html template to render the HTML of the form.
Step 2: Create a View with a slug argument that helps you get the correct form
def payment_method_ajax(request, method): # method is your slug
"""Load a dynamic form based on the desired payment method"""
options = {
'ach': ECheckForm(), # Dynamic form #1
'credit-card': CreditCardForm(), # Dynamic form #2
}
if method in options.keys():
context = {'form': options[method]}
else:
context = None
template = 'your_app_name/form_from_ajax.html'
return render(request, template, context)
Step 3: Define the AJAX url in urls.py
[...
path(
'payment-method-ajax/<slug:method>/', # notice the slug in the URL
views.payment_method_ajax,
name='payment-method-ajax'),
...]
Step 4: Update your template where you'd like the AJAX loaded form to appear
Make some buttons to have the user select an approprate form option
<button id="btn_ach" onclick="load_payment_form(this)">ACH</button>
<button id="btn_credit_card" onclick="load_payment_form(this)">Credit Card</button>
form-fields is where the dynamic form will be loaded
<form id="id-form" style="display: none;">
{% csrf_token %}
<div id="form-fields"></div>
<input type="submit" value="Save Payment Details"/>
</form>
Make sure to add slugs to your main view's context
context = {
'target': 'Add a New Payment Method',
'h1': 'Add a New Payment Method',
'ach': 'Save an ACH Profile',
'credit_card': 'Save a Credit Card Profile',
'slugs': ['ach', 'credit-card'], # Here are the slugs ****
}
Step 5: Load the form with JQuery and the button's onclick
<script>
var ach = 'ACH';
var creditCard = 'Credit Card';
var form_urls ={
ach : '{% url "payment-method-ajax" slugs.0 %}',
creditCard : '{% url "payment-method-ajax" slugs.1 %}',
}
function load_payment_form(btn) {
if(btn.innerText==ach) {
get_url = form_urls['ach'];
type = ach;
}
else if(btn.innerText==creditCard) {
console.log('Load credit card form');
get_url = form_urls['creditCard'];
type = creditCard;
}
$.get({'url': get_url}).done(
function(data) {
document.getElementById('form-fields').innerHTML = data;})
document.getElementById("id-form").style.display = "block";
}
</script>