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')
Related
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 got this system where I want to add in a favoriting feature where when someone clicks on the like button on a card it gets saved and displayed at port/wishlist.html but not able to go about and solve it, here is my Github Repository and some main codes.
models.py
from django.db import models
from django.contrib.auth.models import User
import datetime
YEAR_CHOICES = []
for r in range(1980, (datetime.datetime.now().year + 1)):
YEAR_CHOICES.append((r, r))
class Music(models.Model):
song = models.CharField(max_length=50, blank=False)
pic = models.ImageField(blank=False, null=True)
published_year = models.IntegerField(('year'), choices=YEAR_CHOICES, default=datetime.datetime.now().year)
description = models.CharField(max_length=80)
def __str__(self):
return self.song
class Wishlist(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,null=True)
music = models.ForeignKey(Music, on_delete=models.DO_NOTHING)
views.py
#login_required
def liked(request):
if request.method == "POST":
if user.is_authenticated:
# takes in the specific card id that is been liked and saves it and displays on Port/wishlist.html
music.save()
else:
return HttpResponse("Your card is Invalid")
else:
return HttpResponse("Your request is Invalid")
return render(request, template_name='main/wishlist.html', context={"wishlist": Wishlist.objects.all})
like.js
$(document).ready(function(){
$(".like").click(function(){
$(this).toggleClass("heart");
});
});
I would suggest doing something like this:
Here we create a new url for add to wishlist(add_to_wishlist). In like.js pass music_id through ajax with POST.If a user is login then show user's wishlisted product as heart symbol as red. And you can show wishlisted product through link in template. You can Understand all others in my code. Please try this. Thanks.
urls.py
from django.urls import path
from main import views
app_name = 'main'
urlpatterns = [
path('', views.home, name='home'),
path('signup/', views.signup, name='signup'),
path('wishlist/', views.liked, name='liked'),
path('login/', views.login_req, name='login'),
path('logout/', views.logout_req, name='logout'),
path('add-to-wishlist/', views.add_to_wishlist, name='add_to_wishlist'), # For add to wishlist
]
views.py
def home(request):
wishlisted_list =[]
if request.user.is_authenticated:
wishlisted_list = list(Wishlist.objects.filter(user_id=request.user).values_list('music_id',flat=True).order_by('music_id'))
return render(request, template_name='main/home.html', context={"music": Music.objects.all(),'wishlisted_list':wishlisted_list})
#login_required
def liked(request):
wishlist = {}
if request.method == "GET":
if request.user.is_authenticated:
wishlist = Wishlist.objects.filter(user_id_id=request.user.pk)
else:
print("Please login")
return HttpResponse("login")
return render(request, template_name='main/wishlist.html', context={"wishlist": wishlist})
#login_required
def add_to_wishlist(request):
if request.is_ajax() and request.POST and 'attr_id' in request.POST:
if request.user.is_authenticated:
data = Wishlist.objects.filter(user_id_id = request.user.pk,music_id_id = int(request.POST['attr_id']))
if data.exists():
data.delete()
else:
Wishlist.objects.create(user_id_id = request.user.pk,music_id_id = int(request.POST['attr_id']))
else:
print("No Product is Found")
return redirect("main:home")
like.js
$(document).ready(function(){
$(".like").click(function(){
var attr_id = $(this).attr('attr_id')
var action_url = $(this).attr('action_url')
var that = $(this)
$.ajax({
url: action_url,
type: "POST",
data: {'attr_id': attr_id },
headers: { "X-CSRFToken": $.cookie("csrftoken") },
success: function (result) {
console.log("Success")
that.toggleClass("heart");
},
error: function () {
alert("Please login");
}
});
});
});
home.html
{% load static %}
<link rel="stylesheet" href="{% static 'main/home.css' %}" type="text/css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.0/css/all.css" integrity="sha384-Bfad6CLCknfcloXFOyFnlgtENryhrpZCe29RTifKEixXQZ38WheV+i/6YWSzkz3V" crossorigin="anonymous">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Hey there,
{% if user.is_authenticated %}
<h1>{{user.username}}</h1>
{% else %}
<h1>unknown</h1>
{% endif %}
<a href="{% url 'main:liked' %}" >Wishlist</a>
<section class="cards">
{% for m in music %}
<div class="card">
<div class="top">
<div class="label1">{{m.song}}</div>
{% if m.pk in wishlisted_list %}
{% for i in wishlisted_list %}
{% if m.pk is i %}
<span class="like heart" id="id" attr_id="{{m.pk}}" action_url="{% url 'main:add_to_wishlist' %}"><i class="fa fa-heart"></i></span>
{% endif %}
{% endfor %}
{% else %}
<span class="like" id="id" attr_id="{{m.pk}}" action_url="{% url 'main:add_to_wishlist' %}"><i class="fa fa-heart"></i></span>
{% endif %}
</div>
<div class="middle">
<a href="https://google.com" id="link" target="_blank">
<div class="img-container"><img src="{{ m.pic.url }}"></div>
</a>
</div>
<a href="https://google.com" id="link" target="_blank">
<div class="bottom">
<div class="label4">{{m.description}}</div>
</div>
</a>
</div>
{% endfor %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="{% static 'main/js/like.js' %}" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
</section>
wishlist.html
{% load static %}
<link rel="stylesheet" href="{% static 'main/home.css' %}" type="text/css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.0/css/all.css" integrity="sha384-Bfad6CLCknfcloXFOyFnlgtENryhrpZCe29RTifKEixXQZ38WheV+i/6YWSzkz3V" crossorigin="anonymous">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Hey there,
{% if user.is_authenticated %}
<h1>{{user.username}}</h1>
{% else %}
<h1>unknown</h1>
{% endif %}
<a href="{% url 'main:home' %}" >Go to Home</a>
<section class="cards">
{% if wishlist %}
{% for m in wishlist %}
<div class="card">
<div class="top">
<div class="label1">{{m.music_id}}</div>
<span class="like" id="id" attr_id="{{m.music_id.pk}}" action_url="{% url 'main:add_to_wishlist' %}"></span>
</div>
<div class="middle">
<a href="https://google.com" id="link" target="_blank">
<div class="img-container"><img src="{{ m.music_id.pic.url }}"></div>
</a>
</div>
<a href="https://google.com" id="link" target="_blank">
<div class="bottom">
<div class="label4">{{m.music_id.description}}</div>
</div>
</a>
</div>
{% endfor %}
{% else %}
<div class="card">
<div class="middle">
<div class="label1">Your Wishlist is empty...!</div>
</div>
<div class="bottom">
<div class="label4">Go to Shop</div>
</div>
</div>
{% endif %}
</section>
First things first, you need to add a primary key in the Music table assuming you name it as id
In the like.js file, you'll need to make an Ajax call to send the music ID to Django. Pass the music ID to the template when you render it so that you can pass it back during the Ajax call
like.js
$.ajax(path, {
data: {"music_id": 12345},
method: "POST",
success: function (data, textStatus, jqXHR) {
$(selector).toggleClass("heart");
},
error: function () {
console.log("Something went wrong");
}
Now, in you view, you can have something like this
view.py
def add_to_wishlist(request):
data = json.loads(request.body.decode("utf-8"))
user_id = request.user.id
music_id = data.get('domain_name'))
wishlist = Wishlist()
wishlist.user_id = user_id
wishlist.music_id = music_id
wishlist.save()
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)
}
})
/* ############################################################################# */
}
The program open Bootstrap Modal and load Django Form to create new permission, this is works. But when i want in the form add new Ajax call to load dynamically elements in Django ChoiceField appears the error and browser not finish the call never.
I open browser inspect console and appears XMLHttpRequest error
url.py:
path('permisos/', general_views.permission_list,name='permission_list'),
path('permisos/crear', general_views.permission_create, name='permission_create'),
path('permisos/<int:id>/editar', general_views.permission_update, name='permission_update'),
path('permisos/<int:id>/detalle', general_views.permission_detail, name='permission_detail'),
path('permisos/<int:id>/borrar', general_views.permission_delete, name='permission_delete'),
path('permisos/crear/cargar_elementos/', general_views.permission_load, name='ajax_load_permissions'),
never get to call this function from ajax
views.py:
def permission_load(request):
type = request.GET.get('type')
if type == 2: # object
list = ['general', 'billing', 'accounting']
elements = ContentType.objects.filter(app_label__in=list)
elif type == 3: # instance
list = ['general', 'billing', 'accounting']
content_type = ContentType.objects.filter(app_label__in=list)
elements = general_models.content_type.model.objects.all()
elif type == 4: # attribute
list = ['general', 'billing', 'accounting']
content_type = ContentType.objects.filter(app_label__in=list)
elements = general_models.content_type.model.objects.all()
# get instance atributtes
else: # module
elements = general_models.Modules.objects.all()
# other aspect is that i dont know how to load view result in the html choicefield
response = { 'element': elements }
json = simplejson.dumps(response)
return HttpResponse(json, mimetype="text/json")
forms.py:
class CustomPermisisonForm(forms.Form):
name = forms.CharField()
ACTION_TYPE = ((1, ('Ver')),(2, ('Añadir')),(3, ('Modificar')),(4, ('Borrar')))
action = forms.MultipleChoiceField(choices=ACTION_TYPE, label='Acciones', initial=1, widget=forms.SelectMultiple())
PERMISSION_TYPE = ((1, ('Módulo')),(2, ('Objecto')),(3, ('Instancia')),(4, ('Atributo')))
type = forms.ChoiceField(choices=PERMISSION_TYPE, label='Tipo', initial=1, widget=forms.Select(attrs={"data-objects-url":"{% url 'ajax_load_permissions' %}"}))
element = forms.ModelChoiceField(queryset=general_models.Module.objects.all())
permissions.html:
{% block javascript %}
<script src="{% static 'js/permissions.js' %}"></script>
{% endblock %}
# this is the line to open modal
<button type="button" onclick="return openModalPermission('{% url 'general:permission_create' %}')" class="btn btn-outline-primary float-right btn-sm">
<span class="fas fa-plus"></span>
</button>
permission_create.html:
{% load static %}
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form method="POST" action="{% url 'general:permission_create' %}">
{% csrf_token %}
<div class="modal-header">
<h4 class="modal-title">Nuevo Permiso</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{% include 'permission_form.html' %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Crear</button>
</div>
</form>
</div>
</div>
# when comment this line the error disappear but don't work js call
<script src="{% static 'js/permissions.js' %}"></script>
permission_form.html:
{% load widget_tweaks %}
{% load static %}
{% for field in form %}
<div class="form-group{% if field.errors %} has-error{% endif %}">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" %}
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
{% endfor %}
permissions.js:
function openModalPermission(url) {
$('#modal-permission').load(url, function() {
$(this).modal('show');
});
return false;
}
$("#id_type").change(function () {
console.log("js function");
var url = $("id_type").attr("data-objects-url");
var type = $(this).val();
console.log(type);
console.log(url);
$.ajax({
url: url,
data: {
'type': type
},
success: function (data) {
$("#id_element").html(data);
},
error: function (qXHR, textStatus, errorThrown) {
console.log(qXHR)
console.log(textStatus)
console.log(errorThrown)
}
});
return false;
});
Anybody know how to solve this problem ?
Thanks in advance.
SOLVED
permissions.html:
<!-- pass this block to the end of the file -->
{% block javascript %}
<script src="{% static 'js/permissions.js' %}"></script>
{% endblock %}