Follow on from my last question, I have a django web app which I am trying to use to display data on a HTML page with data from a database using the JsonResponse method. The website allows users to enter the details of a new product. I am trying to design it so that when they enter the details, a Div underneath will automatically update and show the new item that has been entered as well as the existing items in the database. Here is my code:
The index page:
<!DOCTYPE html>
<html>
<body>
<div>
<h2 id="title">Create product</h2>
<input id="name">Name</input>
<br>
<input id="description">Description</input>
<br>
<input id="price">Price</input>
<br>
<button id="add-product">ADD PRODUCT</button>
</div>
<div id="productList">
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
document.getElementById('add-product').onclick = function(){
sendData();
getData();
}
function sendData(){
var order = {
name: document.getElementById('name').value,
description: document.getElementById('description').value,
price: document.getElementById('price').value
};
$.ajax({
type: "POST",
url: 'create/product',
data: order,
success: function(newProduct){
console.log("success"),
$('#name').val(""),
$('#description').val(""),
$('#price').val("")
}
});
};
function getData(){
$.ajax({
url: 'view/product',
dataType: 'json',
type: 'GET',
success: function(data){
$.each(data.prod, function(index, element){
$('body').append($('#productList', {
text: element.name
}));
});
}
});
}
</script>
</html>
The views.py file:
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from products.models import Product
from django.http import HttpResponse, JsonResponse
def index(request):
return render(request, 'index.html')
#csrf_exempt
def createProduct(request):
if request.method == 'POST':
name = request.POST.get('name')
description = request.POST.get('description')
price = request.POST.get('price')
newProduct = Product(
name = name,
description = description,
price = price
)
newProduct.save()
return HttpResponse('')
def viewProduct(request):
if request.method == 'GET':
product_list = Product.objects.all()
products=[]
for prod in product_list:
products.append({"name": prod.name, "description": prod.description, "price": prod.price})
return JsonResponse(products, safe=False)
Now I think the getData() method is working as when I include a console.log message in the success part of the function, it works and prints to the console. However, it does not add the details of the products to the Div as I would like. Thanks in advance for any answers to this.
Here you go with the solution
function getData(){
$.ajax({
url: 'view/product',
dataType: 'json',
type: 'GET',
success: function(data){
$('#productList').empty();
$.each(data.prod, function(index, element){
$('#productList').append(element.name);
});
}
});
}
Once you receive the data, first thing you need to empty the productList container, post that append element.name to the productList.
Related
I am using django and I am getting all id from checkboxes and now I want to pass them to my view function, but I don't know how. I've tried request.GET.getlist('vals') but with no success. any suggestions?
events.html:
<script>
$(document).ready(function(){
$("button").click(function(){
type: 'POST';
var vals = [];
$.each($("input[name='checkb']:checked"),function(vals){
vals.push($(this).attr('id'));
});
alert("values: " + vals.join(", "));
});
});
</script>
<td><button><i class="bi bi-sim"></i></button></th>
{% for l in object_list %}
<tr>
<td>
<form>
<label><input type="checkbox" id={{l.pk}} name="checkb"></label>
<form>
...
urls.py:
path('eprint',views.eprint,name='eprint'),
views.py:
def eprint(request):
print('eprint')
v=request.GET.getlist(vals)
ok I finally solved this problem. I am using AJAX to send the id's to my view:
java script in the template:
<script>
$(document).ready(function() {
$("button").click(function() {
var vals = [];
$.each($("input[name='checkb']:checked"), function() {
vals.push($(this).attr('id'));
});
console.log('cons2:',vals)
$.get('eprint/ticked/',{marked: vals})
console.log('after')
});
});
</script>
views.py:
def eprint(request):
print('eprint')
print(request.GET)
I can't find many tutorials on this, mostly could find ones for PHP. I am trying to create a search bar with an autocomplete feature using python Flask, mySQL, and Ajax. I got things working up to capturing the keystroke and selecting from the database. After that, I can't get any of this to display on the client side.
I've tried using a partial page but none of this will display.
server.py file
#app.route("/search", methods=['POST'])
def search():
output = ''
mysql = connectToMySQL("countries_db")
data_received = json.loads(request.data)
data = data_received['query']
var_data = '%' + data + '%'
mysqlQuery = "SELECT name FROM countries WHERE countries.name LIKE '%s' LIMIT 10;" %var_data
result = mysql.query_db(mysqlQuery)
output += '<ul class="list-unstyled">'
if len(result) > 0:
for country in result:
output += '<li>' + country["name"] + '</li>'
else:
output += '<li>Country Not Found</li>'
output += '</ul>'
return render_template("index.html", result=result)
index.html
<li class="search">
<div class="auto">
<img src="{{ url_for('static', filename='search.png') }}">
<input class="search-bar" type="text" id="country" name="country" aria-label="Search through site content"
placeholder="Search for a Country">
<div class="countryList">
{% for country in result %}
<p>{{country.name}}</p>
{% endfor %}
</div>
</div>
</li>
# Ajax
<script type="text/javascript">
$(document).ready(function () {
$('#country').keyup(function () {
var query = $(this).val();
if (query != '') {
$.ajax({
url: "/search",
method: "POST",
data: JSON.stringify({
query: query,
}),
dataType: "JSON",
contentType: 'application/json;charset=UTF-8',
success: function (data) {
data = data.data
$('#countryList').fadeIn();
$('#countryList').html(data)
},
dataType: 'text'
})
}
})
})
ids are refferred using # and class names are referred using . in Jquery. Replace the # before country-list with '.'
I have a Like feature, which works fine for the "Detailed Product". However, I want to add this feature on the main page, where multiple products are shown. Not sure, how to correctly do that.
urls.py:
url(r'^like$', views.like_product, name='like_product')
script in the base.html:
<script type="text/javascript">
$(document).ready(function(event){
$(document).on('click', '#like', function(event){
event.preventDefault();
var pk = $(this).attr('value');
$.ajax({
type: 'POST',
url: '{% url 'like_product' %}',
data: {'id': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: 'json',
success: function(response){
$('#like-section').html(response['form'])
console.log($('#like-section').html(response['form']));
},
error: function(rs, e){
console.log(rs.responseText);
},
});
});
});
</script>
likes.html:
<form action="{% url 'like_product' %}" method="post">
{% csrf_token %}
{% if is_liked %}
<button type="submit" id="like" name="product_id" value="{{ product.id }}" class="btn btn-danger">Dislike</button>
{% else %}
<button type="submit" id="like" name="product_id" value="{{ product.id }}" class="btn btn-primary">Like</button>
{% endif %}
</form>
views.py:
def home(request):
products = Product.objects.all().order_by('-pub_date')
f = ProductFilter(request.GET, queryset=products)
context = {
'filter': f,
}
return render(request, 'product/home.html', context).
def detail(request, product_id):
product = get_object_or_404(Product, product_id=product_id)
is_liked = False
if product.likes.filter(id=request.user.id).exists():
is_liked = True
context = {
'product': product,
'is_liked': is_liked,
'total_likes': product.total_likes()
}
return render(request, 'product/detail.html', context)
def like_product(request):
product = get_object_or_404(Product, id=request.POST.get('id'))
is_liked = False
if product.likes.filter(id=request.user.id).exists():
product.likes.remove(request.user)
is_liked = False
else:
product.likes.add(request.user)
is_liked = True
context = {
'product': product,
'is_liked': is_liked,
'total_likes': product.total_likes()
}
if request.is_ajax():
html = render_to_string('product/likes.html', context, request=request)
return JsonResponse({'form': html})
Likes/Dislikes are being recorded correctly if clicked from the main page, however they are not correctly displayed (actual amount of likes and Dislike button can only be seen on the "Detailed Product" page). I suspect this is because I have id="like" in the likes.html for both buttons. I suspect the jQuery script needs to be changed as well. Not sure how to do that. Thanks in advance for your help.
I assume you are getting ID from URL to details page. It really depends how you are generating the list of products on the page but if you are using loop in templates then just add like button under each product and then use it's id to set up like form.
How can I call a view function that change object field without refresh the page?
views.py
def add_like(request, pk):
book = Book.objects.get(pk=pk)
book.like = True
book.save()
return redirect('book_list')
urls.py
url(r'^add_like/(?P<pk>[0-9]+)/$', views.add_like, name='add_like'),
list.html
[...]
<td><span class="glyphicon glyphicon-heart" style="color: grey;"></span></td>
[...]
Once user click the button, I want to change like status and the tag content to:
<td><span class="glyphicon glyphicon-heart" style="color: red;"></span></td>
I know Ajax can be the answer, but I don't know how to implement it.
Thanks.
Instead of
<td><span class="glyphicon glyphicon-heart" style="color: red;"></span></td>
Use an input and give it an ID like
<td><input style="color: red" class="book btn btn-default glyphicon glyphicon-heart" value="{book.pk}" /></td>
Then according with this example call the AJAX function
<script>
$(".book").on('click', function () {
var id = $(this).val();
$.ajax({
url: '/add_like/',
data: {
'pk': id
},
dataType: 'json',
success: function (data) {
if (data) {
alert(data);
}
}
});
});
</script>
Then update your view with:
from django.http import JsonResponse
def add_like(request):
pk = request.GET.get('pk', None)
book = Book.objects.get(pk=pk)
book.like = True
book.save()
data = {'book', book}
return JsonResponse('data')
I'm trying to create my own like button but I am encountering some issues.
The code use Ajax with Django and I am getting an error message but I don't know what is wrong.
here is the code, mostly inspired by this post.
article\models.py
class Article(models.Model):
user = models.ForeignKey(User, default='1')
titre = models.CharField(max_length=100, unique=True)
[... some unrelated models ...]
slug = models.SlugField(max_length=40)
likes = models.ManyToManyField(User, related_name="likes")
def __str__(self):
return self.titre
#property
def total_likes(self):
return self.likes.count()
article\urls.py
url(r'^like/$', views.like_button, name='like_button'),
article\views.py
#login_required(login_url='/user')
def like_button(request):
if request.method == 'POST':
user = request.user
id = request.POST.get('pk', None)
article = get_object_or_404(Article, pk=id)
if article.likes.filter(id=user.id).exists():
article.likes.remove(user)
else:
article.likes.add(user)
context = {'likes_count': article.total_likes}
return HttpResponse(json.dumps(context), content_type='application/json')
(As you can see I am trying to get the article id and not the slug)
article.html
<div>
{% for a in article %}
[... some unrelated html ...]
<input type="button" class="like" name="{{ a.id }}" value="Like" />
<p>count : {{ a.total_likes }}</p>
{% endfor %}
</div>
<script>
$('.like').click(function(){
$.ajax({
type: "POST",
url: "{% url 'like_button' %}",
data: {'pk': $(this).attr('name'), 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: "json",
success: function(response) {
alert('Company likes count is now ' + response.count_likes);
},
error: function(rs, e) {
alert(rs.responseText); #No Article matches the given query.
}
});
})
</script>
the error say that No Article matches the given query.
What should I change in order to make this work?
From your code I can see that "id="like" is used in a for loop so it make multiple buttons with same ID. ID must be unique
Tryto change id with class like
<div>
{% for a in article %}
[... some unrelated html ...]
<input type="button" class="like" name="{{ a.id }}" value="Like" />
<p>count : {{ a.total_likes }}</p>
{% endfor %}
</div>
<script>
$('.like').click(function(){
var pk = $(this).attr('name');
$.ajax({
type: "POST",
url: "{% url 'like_button' %}",
data: {'pk': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: "json",
success: function(response) {
alert('Company likes count is now ' + response.count_likes);
},
error: function(rs, e) {
alert('Something went wrong.'); #getting this message.
}
});
})
</script>