submit form without refreshing the page - python

I created form contains title, content and image.
I try to submit that form without refreshing the whole page using with django with ajax.
When I submit the form POST method is okay but I get another GET method showing this error.
GET
http://127.0.0.1:8000/media/default.jpg
[HTTP/1.1 404 Not Found 8ms]
And I didn't declare default image in my model.py.
Here is my views.py
def posts(request):
posts = Post.objects.filter(posted_date__lte=timezone.now()).order_by('-posted_date')
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
else:
form = PostForm()
args = {
'form': form,
'posts': posts,
}
if request.is_ajax():
html = render_to_string('posts/post-section.html', context=args, request=request)
return JsonResponse({'pos':html})
return render(request, 'posts/posts.html', args)
also here is my ajax
$(document).on('submit', '.post-form', function(event){
event.preventDefault();
console.log($(this).serialize());
$.ajax({
type: 'POST',
url: $(this).attr('action'),
data: $(this).serialize(),
dataType: 'json',
success: function(response){
$('.post-section').html(response['pos']);
},
error: function(rs, e){
console.log(rs.responseText);
},
});
});
What should I do to submit that post without refreshing the page?

You template 'posts/post-section.html' is trying to load the image in the error when you render it's contents $('.post-section').html(response['pos']);

Related

How to return relative to request django

In my django project, I built a little like-button. The problem is, that I had it only when I take a detailed view on a post, and now want to put it on the home page, where multiple posts are shown. The problem the Like Function of the button returns to the detailed page, but I want to make the return dependent from the url where the like came from, so that I can just scroll ahead on the home page or what ever page am on, without being returned to another page. So here is my views.py Like function:
def PostLike(request, pk):
post = get_object_or_404(Post, id=request.POST.get('post_id'))
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
else:
post.likes.add(request.user)
return HttpResponseRedirect(reverse('post-detail', args=[str(pk)]))
So in a nutshell: how could I change my Like function so that I am returned to the page I liked from?
Your function returns a Redirect, that's why you are redirected to the detail page.
If you want to stay on the same page after clicking 'Like' you could submit a request through Ajax and return a JsonResponse with a message or a value depending on what you get from the database query.
How to do this varies based on what JS library or framework you are using. Here is a simplistic JQuery example:
in views.py
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
def like_or_unlike(request, id):
if request.user.is_authenticated:
try:
post = get_object_or_404(Post, id=id)
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
message = 'You unliked post ' + id
else:
post.likes.add(request.user)
message = 'You liked post ' + id
except:
message = 'Error processing like for post ' + id
else:
message = 'You must be logged in to like a post.'
return JsonResponse({ 'result': message })
in urls.py
from django.urls import path
from . import views
urlpatterns = [
...
path("like/<id>/", views.like_or_unlike),
]
in template.html
<button class="{% if post.liked %}color-blue{% else %}color-white{% endif %}"
id="post_{{ post.id|stringformat:"s" }}"
onclick="postLike( '{{ post.id|stringformat:"s" }}' )"> Like this post </button>
<script>
function postLike(id) {
var element = "#post_" + id
$.ajax({
url: '/like/' + id,
type: 'get',
contentType: 'application/json',
success: function(data) {
console.log(data);
if $(element).hasClass("color-white") {
$(element).removeClass("color-white");
$(element).addClass("color-blue");
} else {
$(element).removeClass("color-blue");
$(element).addClass("color-white");
}
},
error: function(jqXhr, textStatus, errorThrown) {
console.log(errorThrown);
}
});
}
</script>
I think you should use Ajax request for it so you don't even reload page. Just handle it in JavaScript.
Otherwise you can redirect base on request.referer value to go back to the view where click was made

Ajax call is not going to view function django

Hi I am sending request to a django view but its not accessing view function . Both are in same app . And I am using debugging tool so I tried to debug but on my view no call is received and
My ajax call code is like this
$.ajax({
url: '/edit_profile/',
type: 'get', // This is the default though, you don't actually need to always mention it
success: function(data) {
alert(data);
},
failure: function(data) {
alert('Got an error dude');
}
});
url.py
path('edit_profile/', views.edit_profile , name="edit_profile"),
view.py
def edit_profile(request):
print(request)
print(request)
if request.method == 'POST':
return render(request, 'authenticate/edit_profile.html', context)
I am debugging but call is not received in this view function .
You can see live demo here REPL
First do this if you don't want that your view check the csrf token. This can be done by using decorator #csrf_exempt.
view.py
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def edit_profile(request):
print(request)
if request.method == 'GET':
return render(request, 'authenticate/edit_profile.html')
url.py
path('edit_profile/', views.edit_profile , name="edit_profile"),
ajax request
$.ajax({
url: '/edit_profile/',
type: 'GET',// This is the default though, you don't actually need to always mention it
data:{},
success: function(data) {
alert(data);
},
failure: function(data) {
alert('Got an error dude');
}
});

UPLOAD file to django

I try to upload a file to django from html through an ajax call.
CLIENT SIDE:
<input type="file" class="text-field" name="media">
<input type="button" class="btn" value="SEND">
var files;
$('.text-field').change(function(){
files = this.files;
console.log(files);
});
$('.btn').click(function(){
var data = new FormData();
$.each(files, function(key, value){
data.append(key, value);
console.log(key + ' : ' + value);
console.log(value);
});
$.ajax({
type: 'POST',
url: 'url',
enctype: 'multipart/form-data',
data: data,
cache: false,
dataType: 'json',
processData: false,
contentType: false,
success: function(data){
console.log(data);
}
});
BACK side:
#csrf_exempt def my_file(request):
print request.POST
print request.FILES
result:
MultiValueDict: {u'0': [TemporaryUploadedFile: about.php (application/octet-stream)]}
Please help me to understand how I can upload a file
To upload a file through Django, you will most likely have to use django forms. Here is an example as for how to upload a file:
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
instance = ModelWithFileField(file_field=request.FILES['file'])
instance.save()
return HttpResponseRedirect('/success/url/')
else:
form = UploadFileForm()
return render(request, 'upload.html', {'form': form})
As you can see the form validates your input, and then you can save the file in to your server. For more information about this topic please use the django documentation:
https://docs.djangoproject.com/en/1.10/topics/http/file-uploads/

Requests in Django

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.

How to return django form object in an AJAX request from django template?

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>

Categories