I created my first site with Django and I'm trying to make the Ajax "like" button work on the listing posts page, but I have to reload the page to have +1.
My views:
def likes_post(request):
post_id = None
if request.method == 'GET':
post_id = request.GET['post_id']
like = 0
if post_id:
post = Post.objects.get(id = int(post_id))
if post:
like = post.likes + 1
post.likes = like
post.save()
return HttpResponse(like)
My HTML template:
{% for post in posts %}
<div class="post-favourite">
J'aime <i class="fa fa-heart-o likes_count"aria-hidden="true"> {{ post.likes }}</i>
</div>
{% endfor %}
and the Ajax function:
<script type="text/javascript">
$('.like').click(function(){
var ps_id;
ps_id = $(this).attr("data-posts-id");
$.get('/likes_post/', {post_id: ps_id}, function(data){
$(this).prev().find('.like_count').html(data);
});
});
</script>
The Ajax button for the post detail page works by simply replacing the last line with
$('.like_count').html(data);
in your views.py, you should send back data to jquery with JsonResponse
from django.http import JsonResponse
def likes_post(request):
post_id = None
if request.method == 'GET':
post_id = request.GET['post_id']
like = 0
if post_id:
post = Post.objects.get(id = int(post_id))
if post:
like = post.likes + 1
post.likes = like
post.save()
return JsonResponse({'like':like})
and then in your jquery:
<script type="text/javascript">
$('.like').click(function(){
var ps_id;
ps_id = $(this).attr("data-posts-id");
$.ajax({
url: '/likes_post/',
method: 'GET',
data: {
'post_id': ps_id,
},
success: function(data){
$(this).prev().find('.like_count').html(data);
$(this).html(data);
}
});
});
</script>
whatever you send with JsonResponse is accessible in success part of jquery. in this example the like we send is data in success part.
in success part you can write data in your html code
Related
i have a problem and i dont know if im using the good way to solve it , but their is the problem , i have a client list that i show on the client page , by getting all client with a simple
clients = client.objects.all()
so all client can have a lot of sessions, and session have a lot of clients, its like a ManytoMany relation, so what im trynna do its to show the assigned session of client one by one by clicking on a button (the button open a boostrap modal ) , so i tried to send the id of the the chosen client on click and send it into a django view with ajax GET method, and take this ID directly to find all sessions related with this client and return the query to this page , so the ajax is working correctly and i can send the id , but its like the view its not sending anything . so their is my code hope you can help me :
Html (the div im inserting on the forloop client) :
<div class="list-group list-group-me">
<ul class="list-group list-group-horizontal">
<li class="list-group-item">{{ client.name }}</li>
<li class="list-group-item">{{ client.email }}</li>
<li class="list-group-item">{{ client.created_at | date:" M Y" }}</li>
<li class="list-group-item list-group-item-success">Active</li>
<li class="list-group-item">025f55azg5</li>
<li><div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" id="AddSession"
data-id="{{ client.id }}">
Add
</button>
<button type="button" class="btn btn-primary" data-id="{{ client.id }}" >View</button>
</div>
</li>
</ul>
</div>
the view (tryin the .all() just to see if its working) :
class show_session(View):
def get(self, request , id):
Sclient = session.objects.all()
#Sclient = session.objects.filter(client__id=id)
context = { 'Sclient': Sclient }
return render(request, 'coach/addclient.html', { 'Sclient': Sclient })
the model.py :
class session(models.Model):
name = models.CharField(max_length=80)
client = models.ManyToManyField(client, blank=True)
coach = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
created_at = models.DateTimeField(auto_now_add=True)
detail = models.CharField(max_length=256)
def __str__(self):
return self.name
the main view of the page :
def addclient(request):
form = ClientForm
clients = client.objects.filter(affiliation=request.user.id)
Csession = session.objects.filter(coach=request.user.id)
context = {'form': form ,'clients': clients , 'Csession' : Csession}
form = ClientForm()
if request.method == 'POST':
form = ClientForm(request.POST)
print(form)
if form.is_valid():
print('adding client 1133', form)
name = request.POST.get('name')
email = request.POST.get('email')
new_client = client.objects.create(name= name, email=email , affiliation=request.user)
new_client.save()
return JsonResponse({'client': model_to_dict(new_client)}, status=200)
else:
print('not adding client to the form 1333')
return redirect('addclient')
return render(request, 'coach/addclient.html', context= context)
and the ajax function :
$("#AddSession").click(function(){
var dataID = $(this).data('id');
console.log(dataID)
$.ajax({
url:'addclient/'+ dataID +'/added',
data: {
csrfmiddlewaretoken: csrfToken,
id: dataID
},
type : "get",
success: function(response) {
console.log("hey hey session over here");
}
})
});
i dont know if can use just the main view to get the data and display it , and when i try to acess the url of show_session.view , the query set is working but im still tryin to display it on the addclient url
thanks for your time and help !
so i have fixed the problem , i have just used a POST method to send the id of current user to the view then i used the action data attribute to handle multiple post on my view and use the id given by ajax to have the correct queryset and serialized the queryset into a JSON object so ajax can add the session assiciated with the choosen client on click their is the code :
View :
if request.method == 'POST' and request.POST['action'] == 'session':
print("session response")
id = request.POST.get('id')
print(id)
#Sclient = list(session.objects.filter(coach=request.user.id))
Sclient = session.objects.filter(client__id=id)
SerializedQuery = serializers.serialize('json', Sclient)
return JsonResponse(SerializedQuery, safe=False)
Ajax :
$("#AddSession").click(function(){
var dataID = $(this).data('id');
$.ajax({
url: $(this).data('url'),
data: {
csrfmiddlewaretoken: csrfToken,
id: dataID,
action: 'session',
//dataType:"json"
},
type : "post",
success: function(response) {
console.log("hey hey session over here");
console.log(response)
var obj = jQuery.parseJSON(response)
//console.log(obj[1].fields.name)
var Sarray = [];
var Selector = $("#assigned");
var count = $("#assigned span")
console.log(count.length)
//used to limit the number of element on div on first click
if(count.length < obj.length)
{
for (i = 0 ; i < obj.length ; i++) {
// console.log(obj[i].fields.name)
Sarray.push(obj[i].fields.name)
Selector.append('<span class="badge badge-success">'+ obj[i].fields.name +' x </span>')
}
console.log("yoow",Sarray.length)
}
}
})
});
I'm searching for someone who helps me in a Django project with JS, Ajax and jquery.
I'm trying to create something like adding objects on the django-admin page. I used https://www.pluralsight.com/guides/work-with-ajax-django, and almost everything is working fine but...
On my form, I have multiple choice field with authors, when I pressed the button to add a new author, the object is properly saving in DB, but on the form, I can't see a new object. When I reload the page, the new object is on this multiple choice field.
I thought I should refresh the field to see a new object on the list, but I don't know it's the proper way to meet this goal.
[edit]
models.py
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
book_author = models.ManyToManyField(Author,blank=True,)
...
form.py
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = ['name', ]
widgets = {
'name': forms.TextInput(),
}
views.py
I added class SaveAutor
def author_add_view(request):
form = AuthorForm()
return render(request,
"author/custom_create_author.html",
{"form": form})
class SaveAuthor(View):
template_name = "author/custom_create_author.html"
def get(self, request):
author_form = AuthorForm(request)
return render(request,
self.template_name,
{'form': author_form})
def post(self, request):
#assume authorForm has author_name defined
author_form = AuthorForm(data=request.POST)
if author_form.is_valid():
author = Author() #here is class name or form name?
author.name = author_form.cleaned_data['name']
author.save()
return JsonResponse({'author_id': author.id,
'author_name': author.name})
# error response or whatever you want to return
return JsonResponse({'error': 'author form is not valid'})
I had these views registered in urls.py
urls.py
# add an author
path('author/add/', views.author_add_view,
name='author_add'),
# not sure if I should add as_view() at the end
path('author/new-add/', views.SaveAuthor.as_view(),
name='new_author_add'),
When I try check if page with form is displaying properly using the SaveAuthor class based view I get error 'WSGIRequest' object has no attribute 'get', but when I use the author_add_view I got the template.
custom_create_author.html
$("#author-form").submit(function (e) {
// preventing from page reload and default actions
e.preventDefault();
// serialize the data for sending the form data.
var serializedData = $(this).serialize();
// make POST ajax call
$.ajax({
type: 'POST',
url: "{% url '.' %}", //serializer_ajax_mehit_from_vies
data: serializedData,
success: function (response) {
// on successfull creating object
// 1. clear the form.
$("#author-form").trigger('reset');
// 2. focus to nickname input
$("#id_author_name").focus();
},
error: function (response) {
// alert the error if any error occured
alert(response["responseJSON"]["error"]);
}
})
})
{% load static %}
{% load widget_tweaks %}
{% block content %}
<h4>
My author
</h4>
<form id="author-form">
{% csrf_token %}
<p>{{ form.as_p }}</p>
<button class="btn btn-outline-success" type="submit">save</button>
</form>
<br>
{% endblock %}
Here is another page where I'm trying to connect the book with multiple-choice-field author (it's typical form, but I'm enclosing only the button to pop-up the form, where I can add the new author)
add_book.html js code open pop-up windows to create new author
<script type="text/javascript">
$(function () {
$("#create-author").modalForm({
formURL: "{% url 'author_add' %}"
});
})
</script>
<button id="create-author" class="btn btn-primary" type="button" name="button">
<span class="fa fa-plus"/>
</button>
And on this page, I tried to paste your JS code
<script type="text/javascript">
// assume the add author button has an id of add_author_button
$('#create-author').click(function(event){
event.preventDefault();
// assume the text field has an id of author_name
author_name= $('#author_name').val();
create_post(event, author_name);
}
) //<-------- this closing bracket was missing?
function create_post(event, author_name) {
$.ajax({
url: "{% url '.' %}", // the endpoint I'll precise that in comment
type: "POST", // http method
data: {
author_name: author_name,
csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()
},
// handle a successful response - data will be a json object returned from your view method
success: function (data) {
if (data.error === null) {
// assume your author multiple choice select has an id of author_sel
// this will append the new author name to the list and will also
// set the value for this author to be the newly created id so you can
// perform other functions on the author like update and/or delete
$('#author_id').append($('<option/>', {
value: data.author_id,
text: data.author_name,
}));
} else {
// display the error on the page
// and/or write it to the console log
console.log(data.error);
}
},
// handle a non-successful http response
error: function (xhr, errmsg, err) {
// display the error on the page
// and/or write it to the console log
console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
}
});
}
</script>
One closing bracket was missing, so I added in on the JS script.
I had a problem with the endpoint, when I pass the class-based view SaveAuthor(View) (new_author_add by url name) I got the message: the author form is not valid, but when I used author_add_view (author_add by url name) undefined.
The issue is that while you are using AJAX to submit your new author, the author isn't being added to the author's multiple choice field in the current HTML page. Refreshing the page will retrieve the new value but that also does an entire post/refresh loop. Since you are submitting the post using AJAX, you can return the new author's id and name via a JsonResponse and use jQuery to add it to the author's multiple choice field.
views.py
from MyApp.forms import AuthorForm
from MyApp.models import Author
from django.shortcuts import render
from django.views import View
from django.http.response import JsonResponse
class SaveAuthor(View):
template_name = "author/author.html"
def get(self, request):
author_form = AuthorForm()
return render(request,
self.template_name,
{"form": author_form,
"authors":Author.objects.all()})
def post(self, request):
#assume authorForm has author_name defined
author_form = AuthorForm(data=request.POST)
if author_form.is_valid():
author = Author() #here is class name or form name?
author.name = author_form.cleaned_data['name']
author.save()
return JsonResponse({'author_id': author.id,
'author_name': author.name})
# error response or whatever you want to return
return JsonResponse({'error': 'author form is not valid'})Your AJAX
author.html
<!DOCTYPE html>
{% load static %}
<script src="{% static "jquery-3.4.1.min.js" %}"></script>
{% block content %}
<h4>
My author
</h4>
<select id="author_sel" name="author_sel" size="5" class="selectbox">
{% for author in authors %}
<option value="{{author.id}}">{{author.name|capfirst}}</option>
{% endfor %}
</select>
<form id="author-form">
{% csrf_token %}
<p>{{ form.as_p }}</p>
<input type="button" name="button" class="submit_button" id="add_author_button" value="Save">
</form>
<br>
{% endblock %}
<script type="text/javascript">
// assume the add author button has an id of add_author_button
$('#add_author_button').click(function(event){
event.preventDefault();
// assume the text field has an id of author_name
author_name= $('#id_name').val();
create_post(event, author_name);
}) //<-------- this closing bracket was missing?
function create_post(event, author_name) {
$.ajax({
url: ".", // the endpoint I'll precise that in comment
type: "POST", // http method
data: {
name: author_name,
csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()
},
// handle a successful response - data will be a json object returned from your view method
success: function (data) {
if (data.error === undefined) {
// assume your author multiple choice select has an id of author_sel
// this will append the new author name to the list and will also
// set the value for this author to be the newly created id so you can
// perform other functions on the author like update and/or delete
$('#author_sel').append($('<option/>', {
value: data.author_id,
text: data.author_name,
}));
} else {
// display the error on the page
// and/or write it to the console log
console.log(data.error);
}
},
// handle a non-successful http response
error: function (xhr, errmsg, err) {
// display the error on the page
// and/or write it to the console log
console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
}
});
}
</script>
urls.py
from django.urls import path
from . import views
app_name = 'myapp'
urlpatterns = [
# add an author
path('add/', views.SaveAuthor.as_view(), name='author_add'),
]
forms.py
from django import forms
from MyApp.models import Author
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = ['name', ]
widgets = {
'name': forms.TextInput(),
}
models.py
from django.db import models
# Create your models here.
class Author(models.Model):
name = models.CharField(max_length=100)
This is now a complete working example.
I am trying to fetch data from postgres table by clicking a button in the django template page and the fetched data from db should be populated into another div.
For the same, I am using Ajax get call to fetch the data from DB, but I am facing problem that the value is shown as undefined.
With the Ajax call if I populate the target div with the below, it is working.
$('#childContainer').html(10 + Math.floor(Math.random()*91));
But when I try to fetch the data from table, I am getting undefined.
Here is the code which I have written:-
views.py:-
def index(request):
distinctenvapp = Env_app.objects.values('environment_name').distinct()
return render(request, 'envconfigmgmt/index.html', {'distinctenvapp' : distinctenvapp});
def get(self,request, *args, **kwargs):
if self.request.is_ajax():
return self.ajax(request)
def ajax(self, request):
response_dict= {
'success': True,
}
action = request.GET.get('action','')
if action == 'get_appnames':
env_id = request.GET.get('id','')
if hasattr(self, action):
response_dict = getattr(self, action)(request)
envappname = Env_app.objects.get(environment_name='env_id')
response_dict = {
'application_name':envappname.application_name
}
return HttpResponse(simplejson.dumps(response_dict),
mimetype='application/json')
index.html:-
<div><center><table id="t1"><tr>
{% for obj in distinctenvapp %}
<td>
<button id="{{ obj.environment_name }}">
{{ obj.environment_name }}
</button>
</td>
{% endfor %}
</tr></table></center></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$env_id = $(this).attr('id')
$.ajax({
type: "GET",
data: { action: "get_appnames", id: $env_id },
success: function(data){
$("#childContainer").html("<strong>"+data.application_name+"</strong>");
console.log(data);
}
});
//$('#childContainer').html(10 + Math.floor(Math.random()*91));
});
});
</script>
<div id="childContainer"></div>
I expect the data to be fetched in the target child div.
It should show application names like App1, App2 etc, but it is showing undefined.
IF your ajax request returning JSON content then you have to define datatype in Ajax parameter
$.ajax({
type: "GET",
data: { action: "get_appnames", id: $env_id },
dataType: 'json',
success: function(data){
$("#childContainer").html("<strong>"+data.application_name+"</strong>");
console.log(data);
}
});
For more refere this https://api.jquery.com/jquery.ajax/
I think your ajax request doesnt have url so ajax called current page again
current page is a string and doesnt have application_name
be aware that the mimetype argument was removed in Django 1.7. Use content_type instead.
I am using django 1.5, python 2.7 and jquery 1.9. I have a form which has precisely 2 fields i.e. title and document. When I press submit I want the users chosen document to be present in the request.FILES as shown in the view.
When I submit the regular form (without ajax), this works fine, but with ajax I do not get the file field in my request. Any suggestions on how to upload a file using ajax.
HTML:
<form enctype="multipart/form-data" action="{% url 'upload_document' %}" method="post" id="uploadForm">
{% csrf_token %}
<ul>
<li>
<div>Title</div>
<input id="title" type="text" maxlength="200"/>
<div class="error"></div>
</li>
<li>
<div>Upload File</div>
<input id="document" type="file" size="15" />
<div class="error"></div>
</li>
</ul>
<input type="submit" value="submit"/></p>
</form>
FORMS.PY:
class UploadForm( forms.Form ):
document = forms.FileField()
title = forms.CharField(max_length = 200)
def clean(self):
cleaned_data = super(UploadForm, self).clean()
return cleaned_data
def save(self, *args, **kwargs):
title = self.cleaned_data['title']
doc = self.cleaned_data['document']
document = Document(title = title, document = doc)
document.save()
return document
SCRIPT:
<script type="text/javascript">
$("#uploadForm").submit(function(event){
event.preventDefault();
$.ajax({
url : "{% url 'upload_document' %}",
type: "POST",
data : {csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value,
title: document.getElementById('title').value,
//document: document: document.getElementById('document'),
},
dataType : "json",
success: function( response ){
if(response == "True"){
// success
}
else {
//append errors
}
}
});
});
</script>
VIEWs.PY
def upload_document(request):
print request.POST
print request.FILES
if request.is_ajax():
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES, user = request.user)
if form.is_valid():
form.save()
return HttpResponse(simplejson.dumps('True'), mimetype = 'application/json' )
else:
errors = form.errors
return HttpResponse(simplejson.dumps(errors), mimetype = 'application/json' )
The answer to that question is not that simple. First of all if you intend to support old browsers then indeed it gets nasty. You have to deal with hidden iframes and some JavaScript tricks. I do advice using some well-known scripts for that like jQuery-File-Upload.
But the world is evolving and new technologies arise including HTML5. There's a new File API which is available in most modern browsers ( IE10+, FireFox3.6+, Chrome13+, see: http://caniuse.com/fileapi ) which can be used for that. First you need some HTML:
<input type="file" id="file-select" />
Then you can bind to (for example) change event:
$('#file-select').change( handleFileSelect );
and finally the handler itself:
var data = {};
function createReaderHandler(name) {
return function(ev) {
data[name] = ev.target.result;
};
}
function handleFileSelect(ev) {
var files = ev.target.files; // FileList object
// Loop through the FileList
for (var i = 0; i < files.length; i++) {
var file = files[i],
name = file.name || file.fileName,
reader = new FileReader();
reader.onload = createReaderHandler(name);
reader.readAsText(file);
}
}
Once the data is loaded into JavaScript memory (note that the operation is asynchronous) you can send it via AJAX like any other data. There are more options: depending on your file you can read it as a binary data using .readAsBinaryString and so on. Google is your friend. :)
Also I think there already are good scripts for uploading files with a fallback to old methods. This one can be interesting (haven't tried it):
http://www.plupload.com/
I think the issue is in the submit button, change it into normal button
ie, <button type='button' id='submit'>submit</button>(by default all buttons in form are submit)
and the ajax as
$('#submit').on('click',function(){
frm = $(this).parents('form')
$.ajax({
type: frm.attr('method'),
dataType:'json',
url: frm.attr('action'),
data: frm.serialize(),
async: false,
success: function (data) {
console.log('success')
},
error: function(data) {
console.log("Something went wrong!");
}
})
All others will be same
Just try it will work
PLease i need your help, i'm trying to use jeditable to edit a field on a table inside {% for in %}.
editable DIV:
<td><div class="edit" id="{{ c.id }}">{{ c.name|safe }}</div></td>
jeditable code:
<script>
$(document).ready(function(){
$('.edit').editable('/categoryedit/{{ c.id }}/', {
style: 'display: inline'
});
});
</script>
Url:
url(r'^categoryedit/(?P<id>\d+)/$', 'pos.views.CategoryEdit'),
View:
def CategoryEdit(request, category_id):
id = request.POST.get('category_id', '')
value = request.POST.get('value', '')
categoria = Category.objects.get(pk=id)
categoria.name = value
categoria.save()
return HttpResponse(escape(value))
Solution : The problem was that the editable DIV was inside a {% for %} bucle and in that case is needed to use .each en the Javascript like this...
$('.edit').each(function(){
$('.edit').editable('/categoryedit', {
});
});
and is not necessary to pass the parameters in the url ("/category/1") instead is better to get the parameters using ...
c_id = request.POST.get('id')
the View must be like this:
def CategoryEdit(request):
if request.is_ajax():
if request.method == 'POST':
txt = request.POST.get('value')
c_id = request.POST.get('id')
categoria = Category.objects.get(pk=c_id)
categoria.name = txt
categoria.save()
return HttpResponse(txt)
You probably need to add CSRF data to your javascript. I just ran into this and posted it here:
Django and JEditable: CSRF error
One way to see for sure is to use firebug and look at the ajax response coming back from Django. (If the CSRF info is missing, the Jeditable AJAX call throws a 403 Forbidden error.)