i'm following the Django code that dynamically generates cards according to my amount of variables i have in a bank. For each card it consumes data from an API through ajax code. However, my ajax code is not being called every loop. It is called only once. What I can do is wrong, because I need ajax to be called every loop of HTML.
{% block content %}
<div id="auto" class="row">
{% for row in list %}
{% if row.state == 1 %}
<div class="col-xs-6 col-md-4">
<div class="card">
<h5 class="card-header">{{row.description}} - Temperatura Atual (˚C)</h5>
<!--<img class="card-img-top" src="{% static 'img/gauge.png' %}" width="100" height="200" alt="Card image cap">!-->
<canvas id="myChart-{{ forloop.counter }}" class="piechart"></canvas>
<script>
var rowId = {{ row.id }}
console.log(rowId);
readTempDinamic(rowId);
//refresh();
</script>
<p class="text-center font-weight-bold" style="font-size: 0.7rem"><span id="datetime"></span></p>
Show
</div>
</div>
{% endif %}
{% endfor %}
</div>
{% endblock content %}
function readTempDinamic(rowId) {
var endpointTemp = '/api/weatherData/getSensor/1/' + rowId + '/'
console.log(endpointTemp);
/* ############################################################################# */
$.ajax({
method: "GET",
url: endpointTemp,
success: function(data){
var row = []
var value = []
var read_data = []
row = data.row
value = data.value
read_data = data.read_date
generateGaugeCharts(row[0], read_data[0], value[0])
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
})
/* ############################################################################# */
}
Related
Im trying to post the value of a html item(the id of the item) to the view so it can add the item to the cart, however it always posts the value of the last item printed by the django {% for %} even though the html source says the values are different
here is my html
<div class="container">
<div class="row row-cols-2 row-cols-md-3" data-masonry='{"percentPosition": true }'>
{% for product in products %}
<div class="col mb-4">
<div class="card h-100">
{% if product.image %}
<img src="{{ product.image.url }}" class="card-img-top" alt="{{ product.description }}">
{% endif %}
<div class="card-body">
<h5 class="card-title">{{ product.name }}</h5>
<p class="card-text">{{ product.description|slice:":100" }}...</p>
<p class="card-text">${{ product.price }}</p>
<p>
<a class="btn btn-dark gap-2 mb-1" href="{{ product.get_absolute_url }}">View Item</a>
<button class="btn btn-outline-success" id="add-to-cart" value="{{ product.id }}">Add to Cart</button>
</p>
{% if product.in_stock == False %}
<p>
Item is currently out of stock
</p>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
Here is the Ajax
$(document).on('click', '#add-to-cart', function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '{% url "add_to_cart" %}',
data: {
productid: $('#add-to-cart').val(),
csrfmiddlewaretoken: '{{ csrf_token }}',
action: 'post'
},
success: function(json){
},
error: function(xhr, errmsg, err) {
}
});
})
Here is my view
def CartAddView(request):
cart = Cart(request)
if request.POST.get('action') == 'post':
product_id = int(request.POST.get('productid'))
product = get_object_or_404(Product, id=product_id)
cart.add(product=product)
response =JsonResponse({
'price': product.price,
'id': product.id, (here the id returned is always the id of the last element printed by the loop)
})
return response
i tried to make a product detail page and when i call the ajax it works perfectly
when form submit and view return response page will reload the same page and call POST again, I fixed it with
create a new route but render the same page (if you want to render the same page)
change API return return HttpResponseRedirect('url-new')
examaple:
def CartAddView(request):
cart = Cart(request)
if request.POST.get('action') == 'post':
product_id = int(request.POST.get('productid'))
product = get_object_or_404(Product, id=product_id)
cart.add(product=product)
response =JsonResponse({
'price': product.price,
'id': product.id, (here the id returned is always the id of the last element printed by the loop)
})
return HttpResponseRedirect('url')
In my web site I want to show the user ratings - for that I used the infinite scroll but I am facing one problem.
When it first loads the data before calling the <a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a> it is showing the star with the count of vote,but when after calling the <a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a> it is not showing the star.
my views.py
#login_required
def ratings_user(request,pk):
ratings = VoteUser.objects.filter(the_user_id=pk).order_by('-pk')
paginator = Paginator(ratings, 1)
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
return render(request,request.session['is_mobile']+'profile/ratings.html',{'ratings':posts})
html
{% extends 'mobile/profile/base.html' %}
{% block title %}
Ratings
{% endblock %}
{% block leftcontent %}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" rel="stylesheet">
{% endblock %}
{% block middlecontent %}
<div class="infinite-container">
{% for i in ratings %}
<div class="infinite-item">
<div class="w3-container w3-card w3-white w3-round w3-margin">
<img src="{{ i.the_user.profile.avatar.url }}" alt="Avatar" class="w3-left w3-circle w3-margin-right" style="width:40px;height:40px;border-radius:50%;">
{% with user=i.the_user.profile %}{{ user.prenom|title|truncatewords:2 }} {{ user.nom|title|truncatewords:1 }}{% endwith %}
<br>
<span class="stars" data-rating="{{ i.vote.vote }}" data-num-stars="5" ></span>
<hr class="w3-clear">
<p>
{{ i.commentaire|linebreaksbr }}
</p>
<span class="glyphicon glyphicon-user"></span> {% with user=i.the_sender.profile %}{{ user.prenom|title|truncatewords:2 }} {{ user.nom|title|truncatewords:1 }}{% endwith %}
</div>
</div>
{% endfor %}
</div>
{% if ratings.has_next %}
<a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a>
{% endif %}
{% endblock %}
{% block rightcontent %}
{% endblock %}
{% block js %}
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0]
});
</script>
<script>
//ES5
$.fn.stars = function() {
return $(this).each(function() {
var rating = $(this).data("rating");
var fullStar = new Array(Math.floor(rating + 1)).join('<i class="fas fa-star"></i>');
var halfStar = ((rating%1) !== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
var noStar = new Array(Math.floor($(this).data("numStars") + 1 - rating)).join('<i class="far fa-star"></i>');
$(this).html(fullStar + halfStar + noStar);
});
}
//ES6
$.fn.stars = function() {
return $(this).each(function() {
const rating = $(this).data("rating");
const numStars = $(this).data("numStars");
const fullStar = '<i class="fas fa-star"></i>'.repeat(Math.floor(rating));
const halfStar = (rating%1!== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
const noStar = '<i class="far fa-star"></i>'.repeat(Math.floor(numStars-rating));
$(this).html(`${fullStar}${halfStar}${noStar}`);
});
}
</script>
<script>
$(function(){
$('.stars').stars();
});
</script>
{% endblock %}
I have tried to put the <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" rel="stylesheet"> inside the class="infinite-item" but it does not help.what might be the reason for that ? Thanks.
Since yesterday I am on this question I tried everything.
This is another user that has tried to help me here https://stackoverflow.com/a/69930878/15042684 but I did not really understand could you please help me to understand it with some code.
this is his answer:
It doesn't look like .stars() will look for new elements being added to the DOM. You should look for a callback function configuration option within Waypoint.Infinite that you can call .stars() on the new elements.
Assuming you are using waypoint's Infinite Scroll, you can use the onAfterPageLoad callback
onAfterPageLoad
Default: $.noop.
Parameters: $items.
This is a callback that will fire at the end of the request cycle, after new items have been appended to the container. It is passed one parameter, which is a jQuery object of all the items that were appended during the page load.
Note that despite using the jquery convention of $name indicates a jquery object and stating is a jquery object, in this case, trial and error shows that $items are the DOM elements, not a jquery object.
No example provided in the docs, so it will probably look something like:
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0],
onAfterPageLoad: function(items) {
$(items).find(".stars").stars();
}
});
</script>
I am new to Javascript. I wish to change the contents of div on selecting a particular div element.
If I select a div, the text associated with that div contents only should display. I am using a loop to display the contents. It's like a chat application. If a user clicks on a contact the messages associated with that user should display. I am using a loop to display messages and users.
What I have tried is:
Twig code:
{% set msg = query().from('messages').get() %}
{% set to_add =to_name %}
{% set to_details = query().from('users_users').where('id', to_add).get() %}
<div class="container">
<h3 class=" text-center">Messaging</h3>
<div class="messaging">
<div class="inbox_msg">
<div class="inbox_people">
<div class="headind_srch">
<div class="recent_heading">
<h4>{{auth_user().first_name}}</h4>
</div>
<div class="srch_bar">
<div class="stylish-input-group">
<input type="text" class="search-bar" placeholder="Search" >
<span class="input-group-addon">
<button type="button"> <i class="fa fa-search" aria-hidden="true"></i> </button>
</span> </div>
</div>
</div>
<div class="inbox_chat">
{% set newArray = [] %}
{% for msg in msg_details %}
{% if msg.to_name not in newArray %}
<div class="chat_list active_chat" onclick=viewMessage(this)>
<div class="chat_people">
<div class="chat_img"> <img src="https://ptetutorials.com/images/user-profile.png" alt="sunil"> </div>
<div class="chat_ib">
<h5>{{msg.to_name}} <span class="chat_date">{{msg.time}}</span></h5>
</div>
</div>
</div>
{% set newArray = newArray|merge([msg.to_name]) %}
{% endif %}
{% endfor %}
</div>
</div>
<div class="mesgs">
<div class="msg_history">
<div class="incoming_msg">
<div class="incoming_msg_img">
<img src="https://ptetutorials.com/images/user-profile.png" alt="sunil">
</div>
<div class="received_msg">
<div class="received_withd_msg">
<p>{{msg.message}}</p>
<span class="time_date">{{msg.time}}</span></div>
</div>
</div>
<div class="outgoing_msg">
<div class="sent_msg">
<p></p>
<span class="time_date"></span> </div>
</div>
</div>
</div>
</div>
</div></div>
Javascript code:
<script>
function copyText(elementId){
var x = document.getElementById(elementId).textContent;
if(document.getElementById('select-text').value.length == 0)
{
document.getElementById("btn").disabled = false;
document.getElementById(elementId).style.backgroundColor = "lightblue";
document.getElementById('select-text').focus();
document.getElementById('select-text').value += x;
}
else{
document.getElementById('select-text').readOnly = true;
}
}
</script>
What my output looks like
Output
My output shows all the messages, I want to show only the particular user message. How to do so?
What my table looks like:
Table
First of all you have to fetch the data from your table using a query something like to ensure you will get one record from each from_id.
SELECT * FROM msg GROUP BY from_id;
Then you can loop in twig to create the left side elements like,
{% for distinctMsg in distinctMsgs %}
<div class="chat_list active_chat" data-userId="{{ distinctMsg.fromId }}">
<div class="chat_people">
<div class="chat_img"> <img src="https://ptetutorials.com/images/user-profile.png" alt="sunil"> </div>
<div class="chat_ib">
<h5>{{distinctMsg.to_name}} <span class="chat_date">{{distinctMsg.time}}</span></h5>
</div>
</div>
</div>
{% endfor %}
Then in your javascript:-
$(".chat_list").on("click", function(){
// have a look here https://stackoverflow.com/questions/5309926/how-can-i-get-the-data-id-attribute
var userId = $(this).data( "userId" );
// Maybe display a loading icon in the right side div
$.ajax({
type: "POST",
url: "/api/msg/user/history", // your controller url
dataType: 'json',
headers: {
// if you have any headers to set
"Authorization": "Bearer {{ token }}"
},
data:{
"userId" : userId
}
})
.done(function (response) {
// stop displaying the loading icon
// process the response and display message history in right side
})
.fail(function (xhr, status, error) {
// show proper error message
});
});
NOTE: You will have to have jQuery in your page for Ajax functions to work.
I'm trying to implement infinite scroll with django and jquery(Waypoint).
I have a ListView with a pagination of 5, but when waypoint loads second page, AJAX requests are no longer performed so I added the AJAX function on the onAfterPageLoad which helps bring back AJAX function to the newly loaded page.
That's fine, but then it introduces a bug to my code making the page loaded initially (First Page) no longer perform AJAX functions very well. It makes AJAX on the first page run 3 times if I just loaded a third page and makes AJAX on the second page run twice and so on depending on the number of pages loaded already.
I don't know if there are any cool ways to achieve this because I tried using just jquery without waypoint, but still get same errors as I get when using just waypoint making it an error. This is kinda tricky so far.
{% extends "base.html" %}
{% block content %}
{% load static %}
<div class="container" style="max-width:700px">
<div class="px-3 pt-md-5 pb-md-4 mx-auto text-center">
<h1 class="display-4">All Groups</h1>
<p class="lead">List of groups</p>
</div>
<div class="">
<div class="row infinite-container">
{% for group in groups %}
<div class="col-md-12 infinite-item">
<!-- <img class="img-fluid" src="https://picsum.photos/700"> -->
<a class="text-dark" href="{{ group.get_absolute_url }}">
<div class="card mb-4 box-shadow">
<div class="card-body">
<h2 style="font-size:18px;font-weight:bold;min-height:42px;">
{{group.name|truncatechars:50}}</h2>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">{{group.owner}}</small>
<small class="text-muted">{{group.date_created}}</small>
</div>
<p><a class='follow-btn' data-href='{{ group.get_group_follow_api_url }}'
data-likes='{{ page.likes.count }}'
href='{{ group.get_group_follow_url }}'>{{ group.follows.count }}
{% if request.user.profile in group.follows.all %}
Unfollow
{% else %}
Follow
{% endif %}
</a></p>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
<!-- Comment for loading spinner -->
{% comment %}
<div class="d-flex d-none position-fixed" style="top:35vh;left:46vw">
<button class="btn btn-primary loading">
<span class="spinner-border spinner-border-sm"></span>
Loading...
</button>
</div>
{% endcomment %}
<!-- End of comment for loading spinner -->
<div class="row">
<div class="col-12">
{% if page_obj.has_next %}
<a class="infinite-more-link" href="?page={{ page_obj.next_page_number }}"></a>
{% endif %}
</span>
</div>
</div>
</div>
</div>
<script src="{% static "js/jquery.waypoints.min.js" %}"></script>
<script src="/static/js/infinite.min.js"></script>
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0],
offset: 'bottom-in-view',
onBeforePageLoad: function () {
$('.loading').show();
},
onAfterPageLoad: function () {
$('.loading').hide();
$(document).ready(function(){
function updateText(btn, newCount, verb){
btn.text(newCount + " " + verb)
}
$(".follow-btn").click(function(e){
e.preventDefault()
var this_ = $(this)
var badge = this_.find('.unlike-update')
var followUrl = this_.attr("data-href")
var followCount = parseInt(this_.attr("data-follows")) | 0
var addFollow = followCount + 1
var removeFollow = followCount - 1
if (followUrl){
$.ajax({
url: followUrl,
method: "GET",
data: {},
success: function(data){
console.log(data)
var newFollows;
if (data.followed){
// updateText(this_, addLike, "Unlike")
// updateText(this_, data.likescount, badge)
updateText(this_, data.followscount, "Unfollow")
} else {
// updateText(this_, removeLike, "Like")
updateText(this_, data.followscount, "Follow")
// remove one like
}
}, error: function(error){
console.log(error)
console.log("error")
}
})
}
})
})
}})
</script>
{% include 'group/snippets/group_follow.html' %}
{% endblock %}
class GroupListView(LoginRequiredMixin, ListView):
model = Group
paginate_by = 5
context_object_name = 'groups'
template_name = 'group/group_list.html'
ordering = ['-date_created']
I've come across a strange bug in my Django application that has baffled me for the last few days.
Basically one of my dynamic templates stops rendering on the staging server. Everything works fine locally and when push to my staging server all seems fine however, after clicking around a few pages and then navigating back to one of the pages with this template it has suddenly disappeared. If i restart the supervisor processes the template reappears but then disappears again after navigating to other pages.
The weird thing is it's not consistent when it disappears. Sometimes it takes a few times navigating to other pages to disappear.
The template itself has dynamically generated content however even the container divs are not appearing so this leads me to believe that this is not a context error.
Another point about it is that if i stop my supervisor processes and run ./manage.py runserver instead, the problem doesn't seem to happen.
The things i've tried:
I've used django-template-repl to load the url and view the context
the template receives, all the data i expect to be rendered appears to be there.
Any help would be much appreciated, any tips on where to look next.
the view thats rendered:
def list(request):
projects = Project.objects.active()
order = request.GET.get('order', 'popular')
projects = projects.ordered_by(order)
search_q = request.GET.get('search_q')
if search_q:
project_query_terms = ['title', 'short_description', 'who_description']
username_query_terms = [
'user__userprofile__first_name',
'user__userprofile__last_name']
project_query = create_query(search_q, project_query_terms)
username_query = create_query(search_q, username_query_terms) & Q(
name_is_visible__exact=True)
projects = projects.filter(project_query | username_query)
if request.GET.get('sector'):
projects = projects.filter(sector__id=request.GET['sector'])
if request.GET.get('location'):
projects = projects.filter(
location=request.GET['location'],
location_public=True)
form = ProjectFilterForm
form = (form(request.GET, projects=projects)
if request.GET else form(projects=projects))
paginator = Paginator(projects, 9)
page = request.GET.get('page')
try:
projects = paginator.page(page)
except PageNotAnInteger:
projects = paginator.page(1)
except EmptyPage:
projects = paginator.page(paginator.num_pages)
amounts_by_project = Need.objects.amounts_by_project()
amounts_raised_by_project = MoneyDonation.objects.amounts_raised_by_project()
context = {
'body_id': 'project-list',
'projects': projects,
'form': form,
'order': order,
'amounts_by_project': amounts_by_project,
'amounts_raised_by_project': amounts_raised_by_project,
}
template = "_projects-content" if request.is_ajax() else "projects"
template = "projects/" + template + ".html"
return render(request, template, context)
the projects-projects.html template
{% extends 'projects/__base.html' %}
{% load image_tags staticfiles projects %}
{% block content %}
{% include 'projects/_projects-content.html' %}
{% endblock %}
{% block scripts %}
<script>
FCC.drawDonuts('.col-project');
jQuery(function updateWithFilters($){
function queryWithParams() {
var getParams = '';
$('#project-filter-form select').each(function(i) {
getParams += (i === 0) ? '?' : '&';
getParams += this.name + '=' + $(this).children('option:selected')[0].value;
});
$.get({% url 'projects' %} + getParams, function(res){
$("#projects-content").html(res);
updateWithFilters($);
FCC.drawDonuts('.col-project');
});
}
$('#project-filter-form select').change(function(e){
queryWithParams();
});
$('#reset-filters').click(function(e) {
e.preventDefault();
$('#project-filter-form select option:selected').each(function(){
$(this).prop('selected', false);
queryWithParams();
});
});
});
</script>
{% endblock %}
the _projects-content.html
<div id='projects-content'>
{% include 'projects/_projects-filters.html' %}
{% include 'projects/_projects-projects.html' %}
</div>
the _projects-projects.html
<section class="section hp-projects">
<div class="container">
<div class="row">
<div class="col-xs-12 sub-header">
<sub-header>
<h2>Browse all projects</h2>
</sub-header>
</div>
{% if not projects %}
<p>No projects match your search.</p>
{% endif %}
{% for project in projects %}
<div class="col-xs-12 col-sm-6 col-md-4">
{% include '_project-thumbnail.html' %}
</div><!--col-->
{% endfor %}
</div><!--row-->
<div class="row">
<div class="col-xs-12">
{% with projects as collection %}
{% include 'pagination.html' %}
{% endwith %}
</div>
</div>
</div><!--container-->
</section>
_project-thumbnail.html
{% load total staticfiles projects %}
<div class="project-container">
<header>
<a href="{% url 'project_detail' project.id %}" class="project">
<h5 class="project-title">{{ project.title }}</h5>
</a>
</header>
<figure>
<div class="img-wrap">
<a href="{% url 'project_detail' project.id %}" class="project">
<img class="img-responsive" src="{{ MEDIA_URL }}{{ project.profile_image }}" alt="project image" />
</a>
</div>
<figcaption>{{ project.short_description }}</figcaption>
</figure>
<div class="row three-donuts">
<div class="col-xs-6">
{% include "projects/_project-donate-thumbnail.html" %}
</div>
<div class="col-xs-6">
{% include "projects/_project-volunteer-thumbnail.html" %}
</div>
</div>
</div><!--box-container-->
_project-donate-thumbnail.html is the template that is not rendering after navigating to another page
here's the content of the file but as i said nothing inside this renders once you navigate away from this page after a fresh server restart.
however the _project-volunteer-thumbnail stays completely fine. It is just the donate-thumnail that disappears.
_project-donate-thumbnail.html
<div id="project-{{ project.id }}-donate" class="col-project this-project-donate">
<span class="percentage">
{% if project.donate_aim %}
{{ project.donate_percent }}%
{% endif %}
</span>
</div>
<div class="equation">
£{{ project.donate_status }}
<span class="desired-amount">/ £{{ project.donate_aim }}</span>
</div>
<div class="button-link-wrapper">
{% if project.donate_aim %}
donate
{% else %}
<span class="button graph-button donate deactivated">donate</span>
{% endif %}
</div>
again any tips on where to look next would be helpful