HTMX, Django - update part of page - javascript

I've started with HTMX and I want to use it to refresh part o page after pressing button on pop-up page. The button is adding clicking user as participant in an event. I going true tutorials and example which mostly present cases with forms and I don't know how to approach this update with it.
I'm pretty sure I should use hx-ws, but it is just completely unclear for me how.
chall-interface.html (here is a part which I want to update)
{% load static %}
{% load tagz %}
<div id='chall-interface' class="card-bottom mb-2">
<button onclick="call('challFollows',{'id':'{{chall.id}}'}, this)" class='icon icon-s rounded-sm float-end background-transparent mb-2 me-1 color-white'><i class="font-12 fa fa-heart {% followedChall user chall %}"></i></button>
<button href="#" data-menu="comment-section" class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
<i class="font-12 fa fa-comments color-white"></i>
</button>
{% if chall.dealine_is_over %}
<button href="#" data-menu="rules" class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
<i class="font-12 fa color-white {% changeJoinButton user chall %}""></i>
</button>
<!-- Here is a code I'm asking about -->
{% if user == userParticipationStatus.user %}
<a href="/addResponse/{{chall.id}}" class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
<i class="font-12 fa fa-plus-square color-white"></i>
</a>
{% else %}
{% endif %}
<!-- Here is a code I'm asking about -->
{% if chall.user == user %}
<button class="icon icon-s rounded-sm float-end background-transparent mx-1 mb-2">
<i class="font-12 fa fa-pen color-white"></i>
</button>
{% else %}
{% endif %}
{% else %}
{% endif %}
<div class="card-bottom mb-1 w-25">
{% if chall.profile.id == None %}
{% elif chall.user == user %}
{% else %}
{% endif %}
<span class="float-start mx-3"><i>{{chall.profile.nickname}}</i></span>
</div>
</div>
It is added as {% include "include/chall-interface.html" %} in main html file from which a pop-up is activated
Here is a pop-up
{% load tagz %}
<div id="rules" class="menu menu-box-modal rounded-m" data-menu-width="350">
<div class="card card-style" style="margin: 0px !important">
<div class="content">
<strong class="font-12 mx-1">Rules</strong>
<span class="color-theme font-14 d-block mx-1">{{chall.rules}}</span>
<!-- This is the button -->
<button onclick="call('challParticipates',{'id':'{{chall.id}}'}, this)" class="close-menu btn btn-m float-end rounded-xl shadow-xl text-uppercase font-800 bg-highlight mx-1 my-2"><i>{% changeJoinButton2 user chall %}</i></button>
<!-- This is the button -->
<button data-bs-dismiss="modal" class="close-menu btn btn-m float-end rounded-xl shadow-xl text-uppercase font-800 bg-highlight mx-1 my-2"><i>Exit</i></button>
</div>
</div>
</div>
Here is a call function activated by the button:
function call(url, info, element) {
eventStatus = false
fetch("/"+url+"/", {
method: 'POST',
headers: {'X-CSRFToken': getCookie('csrftoken')},
body: JSON.stringify(info)
}).then(response => response.text())
.then(responseData => {
dataParsed = JSON.parse(responseData);
console.log(dataParsed)
if (dataParsed.eventStatus) {
element.firstElementChild.classList.add("color-gold");
element.firstElementChild.classList.remove("color-white");
}
else {
element.firstElementChild.classList.remove("color-gold");
element.firstElementChild.classList.add("color-white");
}
})
.catch(err => {
// if any error occured, then catch it here
console.error(err);
});
}
View.py
class ChallView(LoginRequiredMixin, TemplateView):
login_url = '/chalth/login'
redirect_field_name = ''
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
chall = Chall.objects.get(id=kwargs.get("id"))
context['chall'] = chall
currentUser = self.request.user
context['userParticipationStatus'] = Participates.objects.filter(user = currentUser, chall = chall).first()
return context
#login_required(login_url = '/chalth/login')
def ChallParticipatesView(request):
data = json.loads(request.body)
id = data.get("id", False)
if id:
challParticipate = Participates.objects.filter(chall_id=id, user=request.user).first()
eventStatus = False
if challParticipate:
challParticipate.delete()
eventStatus = False
else:
challParticipate=Participates()
chall = Chall.objects.get(id=id)
eventStatus = True
if chall:
challParticipate.chall = chall
challParticipate.user = request.user
challParticipate.save()
else:
return HttpResponse(status = 400)
else:
return HttpResponse(status = 400)
return HttpResponse(json.dumps({"eventStatus": eventStatus, "id": id}), status = 200)

As far as I can understand from your code, I can't see htmx in action.
I suggest you first try using the inline way, for example:
<button hx-post="/clicked"
hx-trigger="click"
hx-target="#parent-div"
hx-swap="outerHTML"
>
Click Me!
</button>
to see if your problem is about:
the server that doesn't return valid HTML
the server that returns an error (that will stop the swap)
the wrong usage of htmx APIs
Also make sure to know what the properties:
hx-trigger
hx-target
hx-swap
do.
I hope I have helped 😊

Related

Need to save all answers from a user on every questions related on a specific Quiz

I want to save after submitting all answers from a user of all questions related on a specific Quiz.
The logical is :
I've got Quiz, Questions. Question car link to Quiz and when I choose a quiz all questions link to are shown on webpage with javascript (design).
After submiting I need to get all checkbox checked and save into UserResponse.
Models
class Question(models.Model):
objects = None
question = models.CharField(max_length=200, null=True)
description = models.CharField(max_length=255, null=True)
question_pic = models.ImageField(upload_to='poll/', storage=fs, null=True)
choices = models.ManyToManyField(Answer, related_name='QuestionsChoices')
mandatory = models.BooleanField(default=True)
multiple = models.BooleanField(default=False)
randomize = models.BooleanField(default=False)
class Quiz(models.Model):
STATUS_CHOICES = (
(1, 'Draft'),
(2, 'Public'),
(3, 'Close'),
)
nom = models.CharField(max_length=200, null=False)
theme = models.ForeignKey(Theme, null=False, on_delete=models.CASCADE)
questions = models.ManyToManyField(Question, related_name='Quizs')
status = models.IntegerField(choices=STATUS_CHOICES, default=1)
published = models.DateTimeField(null=True)
date_added = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now_add=True)
class QuizInstance(models.Model):
objects = None
"""
A combination of user response and a quiz template.
"""
player = models.ForeignKey(User, on_delete=models.CASCADE)
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
start_quiz = models.DateTimeField(auto_now_add=True)
score = models.IntegerField(default=0)
complete = models.BooleanField(default=False)
class UserResponse(models.Model):
objects = None
"""
User response to a single question.
"""
quiz_instance = models.ForeignKey(QuizInstance, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
response = models.ManyToManyField(Answer, related_name="UserResponses")
time_taken = models.DateTimeField(auto_now_add=True)
time_taken_delta = models.DateTimeField(blank=True)
VIEWS (to show all questions from selected quiz)
def show_quiz(request, quiz_id):
try:
quiz = Quiz.objects.get(pk=quiz_id)
except:
messages.error(request, "Ce quiz n'existe pas ;)")
return redirect('poll:show-list')
context = {
'quiz': quiz,
}
return render(request, "poll/show_quiz.html", context)
# IF QUIZ SUBMITED, HERE I NEED TO SAVE ALL ANSWER GAVE BY USER INTO UserResponse
def answer_quiz(request):
context = {}
if request.method == 'POST':
quiz = Quiz.objects.get(pk=request.POST.get('id_quiz'))
player = request.user
quiz_player = QuizInstance.objects.filter(player=player, quiz=quiz)
if len(quiz_player) == 0:
quiz_instance = QuizInstance.objects.create(player=player, quiz=quiz)
else:
context = {
'error': True,
}
return render(request, "poll/answer_quiz.html", context)
TEMPLATES (HTML)
[...]
{% for question in quiz.questions.all %}
<fieldset class="p-4" style="max-width:720px; margin:0 auto;">
<question>
{{ forloop.counter }} - {{ question.question }}
{% if question.question_pic != "" and question %}
<div class="col-12 my-3 rounded-3" id="picQuestionDiv">
<img class="img-thumbnail rounded-3 p-2" src="/media/{{ question.question_pic }}" width="200" />
</div>
{% endif %}
</question>
<reponses class="d-grid gap-4" style="display:block !important; ">
{% if question|is_answer_pic %}
{% for reponse in question.choices.all %}
<input type="checkbox" hidden value="{{ reponse.id }}" name="reponse" id="reponse_{{ reponse.id }}" />
<reponse style="width:calc(50% - 8px + 4px); text-align:left !important;" class="col-6 mb-2 btn btn-reponse reponse" data-id="reponse_{{ reponse.id }}">
<div class="d-flex align-items-center rounded-3">
{% if reponse.answer_pic %}
<img class="card-img-top rounded-3 img-fluid mh-100 cover text-center" style="" src="/media/{{ reponse.answer_pic }}">
{% else %}
<i class="card-img-top rounded-3 mt-2 img-fluid mh-100 cover bi bi-eye-slash fs-1 text-center"></i>
{% endif %}
</div>
<div style="display:inline-block">
<span class="border border-secondary p-0 px-2 rounded-3 letter-reponse-pic bg-light text-secondary" style="">{{ forloop.counter0|show_letter }}</span>
<span class="">{{ reponse.answer }}</span>
</div>
</reponse>
{% endfor %}
{% else %}
{% for reponse in question.choices.all %}
<reponse style="width:calc(50% - 8px + 4px);" class="col-6 mb-2">
<div class="d-flex align-items-center rounded-3 border btn btn-outline-reponse p-2 reponse mb-2">
<span class="border border-secondary p-0 px-2 rounded-3 letter-reponse bg-light text-secondary">{{ forloop.counter0|show_letter }}</span>{{ reponse.answer }}
</div>
</reponse>
{% endfor %}
{% endif %}
</reponses>
<link class="" style="display: block;">
{% if not forloop.first %}
<a class="btn btn-secondary prev">Précédente</a>
{% endif %}
{% if not forloop.last %}
<a class="btn btn-secondary next">Suivante</a>
{% endif %}
{% if forloop.last %}
<button type="submit" class="btn btn-success next">Terminé !</button>
{% endif %}
</link>
</fieldset>
{% endfor %}
I know my method is not very clean ... I use form for Create Question, Quiz, etc ... but for showing Question I can't because need to show specific kind of checkbox if image, and other if not ... Anyway, here my need it just to retrive from POST submitting all data from quiz send by user And save it :)
Thanks for your help

Why html buttons dynamically created by django cannot access my javascript function?

My Django application makes divs dynamically. Each div is a post of a blog post and also I have a like button on each div. Each button will automatically turn into unlike when a user clicks on it without reloading using javascript. I wrote a javascript function for this. Unfortunately, my javascript function works only the last post on a page (As I have pagination property).
document.addEventListener("DOMContentLoaded",function(){
// const colon = document.createElement('div');
// colon.setAttribute('id','colon')
// e.preventDefault()
// const likebtn = document.createElement('button');
// likebtn.setAttribute('class','likebtn btn btn-primary');
// likebtn.setAttribute('class','likebtn');
// document.querySelector('.card-footer').appendChild(likebtn);
// document.querySelector('.likebtn').innerHTML = "Like";
document.querySelector(`#likeform${posts_id}`).addEventListener('submit',(event) => {
event.preventDefault();
like_function();
// return false;
})
// document.querySelector('.likepost').addEventListener('click', ()=> like_function('likepost'));
})
// let is_like = "{{is_like}}";
// let num_like = "{{num_like}}";
function like_function(){
// document.createElement('button').innerHTML = "Love";
// console.log("Updated!")
fetch(`/like/${posts_id}`,{
method:"POST",
body : JSON.stringify({
"is_like" : is_like,
"num_like" : num_like,
})
})
.then(response => response.json())
.then(result => {
if(result.is_like){
console.log("function is liked");
console.log(`${result.is_like} for post ${posts_id}`);
let num_like = result.num_like;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Unlike";
num_like = num_like + 1;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#num_of_likes_${posts_id}`).innerHTML = `${num_like} `
// location.replace("http://127.0.0.1:8000")
}
else{
console.log("function is unliked, back off!");
console.log(`${result.is_like} for post ${posts_id}`);
let num_like = result.num_like;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Like";
num_like = num_like - 1;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#num_of_likes_${posts_id}`).innerHTML = `${num_like} `
// location.replace("http://127.0.0.1:8000")
}
})
}
// function like_function(){
// if (document.querySelector("#like").style.color == "blue"){
// document.querySelector("#like").style.color = "red";
// }else{
// document.querySelector("#like").style.color = "blue";
// }
// }
This is my full javascript code. Here I'm sharing my HTML template,
<div id="posts" class="card">
<ul class="card-body">
{% for posts in page_view %}
<li class="card">
<div class="card-header bg-success">
<h5 class="card-title"><a class="text-light" style="text-decoration: none;" href="{% url 'profile' posts.user.id %}">{{ posts.user }}</a></h5>
<h6 class="card-subtitle text-light">{{ posts.timestamp }}</h6>
</div>
<div class="card-body">
<h3 class="card-text">{{ posts.post }}</h3>
</div>
<div id="likeapost{{posts.id}}" class="card-footer">
{% if request.user in posts.likepost.all %}
<form action="{% url 'likepost' posts_id=posts.id %}" id="likeform{{posts.id}}" method="POST" style="display: inline;">
<!-- {% csrf_token %} -->
<button id="likebtn{{posts.id}}" class="btn btn-link" type="submit">Unlike</button>
</form>
{% else %}
<form action="{% url 'likepost' posts_id=posts.id %}" id="likeform{{posts.id}}" method="POST" style="display: inline;">
<!-- {% csrf_token %} -->
<button id="likebtn{{posts.id}}" class="btn btn-link" type="submit">Like</button>
</form>
{% endif %}
<small id="num_of_likes_{{posts.id}}" class="num_of_likes">{{ posts.likepost.all.count }}</small>
{% block script %}
<script>
posts_id = "{{ posts.id }}";
is_like = "{{is_like}}";
num_like = "{{ posts.likepost.all.count }}";
</script>
<script src="{% static 'network/controller.js' %}"></script>
{% endblock %}
<button class="btn btn-link" style="text-decoration: none;">Comment</button>
View Post
{% if request.user.id is posts.user.id %}
Edit
{% endif %}
<!-- <div class="likepost"></div> -->
</div>
</li>
{% empty %}
<h6>No post availabel 😔</h6>
{% endfor %}
</ul>
</div>
This is my HTML template. All the buttons should work like this,
Only this one button works perfectly, but others do not. This is what happening.
What should I do? I am about 90% done. Please help.

can't refresh the data in a DIV python Django nor the page after a jquery

Let me start by saying I have 2 variables in an HTML template(messages and users) and I have multiple buttons that when one of them is clicked it calls a jquery code that sends a post request to a Django server and it returns an update to a variable(messages)
however, it's not updating the loop, I also tried to return a new HTML page that contains the new variable updated but the jquery is not updating the whole page with the new HTML
if I can update the variable alone it would be better and if I can't do that how can I make jquery use the new HTML page
the python code i used to return the update to the varialbe messages:
if request.method == 'POST':
send=Message.objects.filter(from_id=request.POST.get('userId'),to_id=2)
rec=Message.objects.filter(from_id=2,to_id=request.POST.get('userId'))
messages=sorted(chain(rec, send),key=lambda instance: instance.id,reverse=True)
print(messages)
return HttpResponse(list(messages))
and the code i used to return new HTML template:
m = Message.objects.filter(to_id=2).order_by('-id')
users = {}
for i in m:
if users.get(i.from_id.username) == None:
users[i.from_id.username] = User.objects.get(id=i.from_id.id)
users = list(users.values())
send=Message.objects.filter(from_id=users[0].id,to_id=2)
rec=Message.objects.filter(from_id=2,to_id=users[0].id)
messages=sorted(chain(rec, send),key=lambda instance: instance.id,reverse=True)
if request.method == 'POST':
send=Message.objects.filter(from_id=request.POST.get('userId'),to_id=2)
rec=Message.objects.filter(from_id=2,to_id=request.POST.get('userId'))
messages=sorted(chain(rec, send),key=lambda instance: instance.id,reverse=True)
print(messages)
return render(request,'psych.html',{"users":users, "messages":list(messages)})
return render(request,'psych.html',{"users":users, "messages":list(messages)})
the HTML code and jquery code that uses the variable and try to update it
function newUser(id){
$.ajax({
type: 'POST',
url:'/psych.html/',
data:{
userId:id,
},
success: function(data){
console.log(data);// the data returnd are correct and as needed
//but i cant make it update the messages
$('#messageDiv').load(document.URL + ' #messageDiv');
}
})
}
{% for i in users %}
<li class="">
<button type="button" class="btn" onClick="newUser({{i.id}})">
<div class="d-flex bd-highlight">
<div class="img_cont">
<!-- here was an image ----------------------------------------------->
</div>
<div class="user_info">
<span>{{i.id}}</span>
</div>
</div>
</button>
</li>
{% endfor %}
<!-- The varialbe that i'm trying to update is called messages bottom -->
{% for o in messages %}
{% if o.to_id.id != 2 %}
<div class="d-flex justify-content-start mb-4">
<div class="img_cont_msg">
<!-- here was an image-->
</div>
<div class="msg_cotainer">
{{o.message}}
<!-- <span class="msg_time">{{o.time}}</span> -->
</div>
</div>
{% else %}
<div class="d-flex justify-content-end mb-4">
<div class="msg_cotainer_send">
{{o.message}}
<!-- <span class="msg_time_send">{{o.time}}</span> -->
</div>
<div class="img_cont_msg">
<!-- here was an image-->
</div>
</div>
{% endif %}
{% endfor %}
if it helps i did it before and updated the messages from jquery but i used form and there was only 1 variable i will add the code to that too
$(document).on('submit','#submitMessage', function (e){
e.preventDefault();
$.ajax({
type: 'POST',
url:'/psych.html/',
data:{
message:$('#messageHolder').val(),
csrfmiddlewaretoken: $('input[message=csrfmiddlewaretoken]').val(),
},
success: function(data){
// it work like charm here
$('#messageDiv').load(document.URL + ' #messageDiv');
}
})
})
{% for o in messages %}
{% if o.to_id.id == 2 %}
<div class="d-flex justify-content-start mb-4">
<div class="img_cont_msg">
<!-- here was an image-->
</div>
<div class="msg_cotainer">
{{o.message}}
<!-- <span class="msg_time">{{o.time}}</span> -->
</div>
</div>
{% else %}
<div class="d-flex justify-content-end mb-4">
<div class="msg_cotainer_send">
{{o.message}}
<!-- <span class="msg_time_send">{{o.time}}</span> -->
</div>
<div class="img_cont_msg">
<!-- here was an image-->
</div>
</div>
{% endif %}
{% endfor %}
<form id="submitMessage" >
{% csrf_token %}
<div class="card-footer">
<div class="input-group">
<div class="input-group-append"></div>
<input name="message" class="form-control type_msg" placeholder="Type your message..." id="messageHolder">
<div class="input-group-append">
<button type="submit" class="btn">
<span class="input-group-text send_btn" ><i class="fas fa-location-arrow"></i></span>
</button>
</div>
</div>
</div>
</form>
Try this
$("#messageDiv").load(location.href+" #messageDiv>*");
i figured the problem and it was because i didn't know that
$("#messageDiv").load(location.href+" #messageDiv>*");
would make a GET request so all I did was adding the necessary data to the URL and then change the URL too(so if the client refreshed the page it would stay in the same spot) without refreshing the page and then do the command app there
if it could help anyone please look at the code below:
function newUser(id){
var url = document.URL;
url = url.split('/');
url[url.length-2] = id;
url = url.join('/');
window.history.pushState("object or string", "my website name", url);
$('#messageDiv').load(url + ' #messageDiv');
}
sadly i don't know how to do post requst then load the page please if you know comment down bellow so someone else might get help from it

Django CBV form submission returned JSON is displayed as a new page

I am using Django 3.2
I am creating a simple newsletter subscription form. The form submission returns JSON to the frontend, which should then be used to update parts of the page - however, when I post the form, the JSON string is displayed as text on a new page.
Here is the route that calls the view:
urlpatterns = [
# ...
path('subscription', BlogsubscriberCreateView.as_view(), name='subscription-post'),
# ...
]
Here is my class based view:
class BlogsubscriberCreateView(CreateView):
model = BlogPostSubscriber
form_class = BlogSubscriptionForm
http_method_names = ['post']
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
content_type = "application/json"
if not form.is_valid():
return JsonResponse({'ok': 0, 'msg': form.errors.get('email')[0]}, content_type=content_type, status=200)
else:
email = form.cleaned_data.get("email")
subscriber = BlogPostSubscriber(email= email)
subscriber.save()
# send email to confirm opt-in
email_message='Please confirm your subscription'
message = f"A confirmation email has been sent to {email}. Please confirm within 7 days"
return JsonResponse({'ok': 1, 'msg': message}, content_type=content_type, status=200)
Here is a snippet of the HTML containing the form:
<div class="col-lg-8 content">
<form id="blog-subscription" action="{% url 'blog:subscription-post' %}" method="post">
{% csrf_token %}
<br />
<h3>Some title</h3>
<br />
<p>Lorem ipsum ...</p>
<br />
<h4 id='submit-response-h4'>SUBSCRIBE TO OUR BLOG</h4>
<div id="submit-response" class="input-group">
<span id="email-error"></span>
<input type="email" id="blog-subscription-email" name="email" class="form-control" placeholder="Enter your email" required="true">
<span class="input-group-btn">
<button id="subscribe-btn" class="btn" type="submit">Subscribe Now</button>
</span>
</div>
</form>
Here is the Javascript that is responsible for updating the page:
$().ready(function() {
$('form#blog-subscription button#subscribe-btn.btn').on('click', function(e){
let email = $('#blog-subscription-email').val().trim().toLowerCase();
if (email.length && isValidEmail(email)){
e.preventDefault();
$.post({
url: "{% url 'blog:subscription-post' %}",
dataType: 'json',
data: {
email: email,
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (data){
let ok = data.ok;
if (ok){
if ($('#submit-response-h4').length){
$('#submit-response-h4').remove();
}
$('#submit-response').text(data.msg);
}
else{
$('#email-error').text(data.msg);
}
}
});
}
});
});
I placed an alert note in my Javascript and realised that it is simply not being called at all. I don't understand what is going on - if the Javascript is not being called - how does JQuery know to call the post function to the correct URL? (form has no action attribute!).
Typical example of a response (with a bad email) shown at http://example.com/path/to/subscription:
{"ok": 0, "msg": "Please use a different email service provider"}
What is causing this problem - and how do I fix it?
This code populates a modal with relevant images. It is not exactly the same as your issue, but this does work so should be transferable with amendments.
js
function modal_form(form_url){
var modal_id = 'modal-form';
$.ajax({
type: 'GET',
url: form_url,
cache: false,
success: function (data, status) {
$('#carouselModal').html(data);
$('#carouselModal').modal('show');
}
});
}
html
<img class="d-block w-100" src="{% thumbnail image.file 'carousel_main' subject_location=image.file.subject_location %}" alt="{{ organisation.name }} - {{ forloop.counter }}" itemprop="image" onclick="modal_form('{% url "providers:carousel-modal" organisation.id "carousel_photos" %}')">
urls
path('carousel-modal/<int:pk>/<str:gallery>/', views.CarouselModal.as_view(), name="carousel-modal"),
views
class CarouselModal(DetailView):
model = models.Organisation
template_name = "providers/extras/gallery_modal.html"
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
gallery = self.kwargs['gallery']
if gallery == 'carousel_photos':
ctx['images'] = self.object.carousel_photos
elif gallery == 'propertyimages':
ctx['images'] = self.object.propertyimages_set.all()
if self.request.user_agent.is_mobile:
ctx['image_size'] = 'mobile_modal_carousel_slide'
elif self.request.user_agent.is_tablet:
ctx['image_size'] = 'tablet_modal_carousel_slide'
else: ctx['image_size'] = 'modal_carousel_slide'
try: ctx['show_all'] = self.object.is_premium
except: ctx['show_all'] = False
return ctx
gallery_modal.html
{% load static thumbnail %}
<div class="modal-dialog carousel-modal" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="mainCarousel" class="carousel slide thumbnail-carousel" data-ride="carousel">
<div class="thumbnail-carousel__main">
<div class="carousel-inner">
{% for image in images %}
{% if show_all or forloop.first %}
<div class="carousel-item{% if forloop.first %} active{% endif %}">
<img class="d-block w-100" width="100%" src="{% thumbnail image.file image_size subject_location=image.file.subject_location %}" alt="{{ image.name }}" itemprop="image" >
</div>
{% endif %}
{% empty %}
{% include 'providers/detail/stock_carousel.html' %}
{% endfor %}
</div>
{% if show_all and images.count > 1 %}
<a class="carousel-control-prev" href="#mainCarousel" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#mainCarousel" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
{% endif %}
</div>
</div>
</div>
</div>
</div>
I've just realised in this example I'm not return a JSONResponse, but again, I think the principle is good

Add Like button with Django + Ajax

Hi I create my first project like stackoverflow(question-answer). I used this guid from Tango with Django http://www.tangowithdjango.com/book17/chapters/ajax.html to add like button with ajax. And nothing hapened. Don't see any request in console. I'm noob in Django, and it's my first encounter with jquery.
apps/questions/models:
class Answer(models.Model):
text = models.TextField()
date = models.DateTimeField(default=datetime.datetime.now)
likes = models.IntegerField(default=0)
resolve = models.IntegerField(default=0)
author = models.ForeignKey(CustomUser)
question = models.ForeignKey(Question)
apps/questions/views:
#login_required
def add_like(request):
ans_id = None
if request.method == 'GET':
ans_id = request.GET['answer_pk']
likes = 0
if ans_id:
ans = Answer.objects.get(id=(int(ans_id)))
if ans:
likes = ans.likes + 1
ans.likes = likes
ans.save()
return HttpResponse(likes)
apps/questions/ulrs:
url:
url(r'add_like/$', views.add_like, name='add_like'),
question.html:
{% for answer in answers %}
<div class="container-fluid no-padding">
{{ answer.text }}
</div>
<div class="container-fluid author-question">
<p>posted: {{ answer.date.day|stringformat:"02d" }}.{{ answer.date.month|stringformat:"02d"}}.{{ answer.date.year}}</p>
<p>by: {{ answer.author.username }}</p>
</div>
{% if user.is_authenticated %}
<button class="btn btn-default" type="button" id="likes" data-ansid="{{ answer.id }}">
like | <strong id="like_count">{{ answer.likes }}</strong>
</button>
{% endif %}
js/ajax.js:
$('#likes').click(function(){
var ansid;
ansid = $(this).attr("data-ansid");
$.get('/questions/add_like/', {answer_id: ansid}, function(data){
$('#like_count').html(data);
$('#likes').hide();
});
});
Since you are creating buttons in a for loop, and naming them the same way, you have multiple elements on the page with the same id. Because of this you get unpredictable results. You should either give each button its own id, or change the jQuery selector to select the buttons based on the appropriate class.
For example, you could have:
{% for answer in answers %}
<div class="container-fluid no-padding">
{{ answer.text }}
</div>
<div class="container-fluid author-question">
<p>posted: {{ answer.date.day|stringformat:"02d" }}.{{ answer.date.month|stringformat:"02d"}}.{{ answer.date.year}}</p>
<p>by: {{ answer.author.username }}</p>
</div>
{% if user.is_authenticated %}
<button class="btn btn-default likes-button" type="button" data-ansid="{{ answer.id }}">
like | <strong id="like_count">{{ answer.likes }}</strong>
</button>
{% endif %}
{% endfor %}
And then for the javascript
$('.likes-button').click(function(){
var ansid;
ansid = $(this).attr("data-ansid");
$.get('/questions/add_like/', {answer_id: ansid}, function(data){
$('#like_count').html(data);
$('#likes').hide();
});
});

Categories

Resources