Django ajax search button more than one data
Question:
I have a django project. In this project, I made a search box with ajax, but the same data is coming more than once. Is the problem in ajax? or is the problem in django? I am not sure. Please help me.
Hey guys.I have a django project. In this project, I made a search box with ajax, but the same data is coming more than once. Is the problem in ajax? or is the problem in django? I am not sure. Please help me.
Hey guys.I have a django project. In this project, I made a search box with ajax, but the same data is coming more than once. Is the problem in ajax? or is the problem in django? I am not sure. Please help me.
my html code
enter code here
<form class="search-content" method="POST">
{% csrf_token %}
<input type="text" name="text" placeholder="Ne Aramıştınız?" id="searchInputChange">
<button>Ara <i class="fas fa-search"></i></button>
</form>
<div class="all-dietitans-content">
<div id="null-search-dietitians">
Aradığınız sonuç bulunamadı. Lütfen aradığınız kelimeyi gözden geçiriniz.
</div>
{% for posts in posts%}
<div class="dietitans" data-firs-load="true">
<div class="left-image">
<img src="{{posts.photo}}" alt="">
<a onclick="openVideoModal(event)" data-iframe-link="{{posts.video}}">
<i class="far fa-play-circle"></i>
<br>
İzle
</a>
</div>
<div class="right-content">
<div class="dietitans-infos">
<div class="left">
<div class="name">
{{posts.isim}} {{posts.soyisim}}
</div>
<div class="degree">
{{posts.uzmanlik}}
</div>
<div class="stars">
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star notStar"></i>
</div>
</div>
<div class="right">
<div class="item">
<div class="title">
Yorum Sayısı
</div>
<div class="number">
{{posts.yorum_sayi}}
</div>
</div>
<div class="item">
<div class="title">
Danışan Sayısı
</div>
<div class="number">
{{posts.danisan_sayi}}
</div>
</div>
</div>
</div>
<div class="dietitans-services-content">
<div class="dietitans-description">
<div>Uzmanlıklar :</div>
<div> {{posts.hizmetler}} </div>
</div>
<div class="buttons-and-text">
<div class="buttons">
<div class="button-style-2">
<a href="{% url 'diyetisyen' slug=posts.slug %}">Profili İncele</a>
</div>
<div class="button-style-1">
<a href="{%url 'randevu' slug=posts.slug %}">Randevu Al</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
my ajax code
enter code here
const nullDietitans = document.getElementById('null-search-dietitians')
const pagination = document.querySelector('.pagination')
const dietitiansContent = document.querySelector(".all-dietitans-content")
const dietitansFirstLoad = document.querySelectorAll('.all-dietitans-content > .dietitans[data-firs-load="true"]')
const searchInputChange=document.querySelector("#searchInputChange");
searchInputChange.addEventListener('input',(e)=>{
nullDietitans.style.display = 'none'
let searchValue=e.target.value.trim();
if(searchValue.length>=3){
if(searchValue === ''){
dietitansFirstLoad.forEach(element=>{
element.style.display = 'flex'
})
pagination.style.display = 'flex'
document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element=>{
element.remove()
})
nullDietitans.style.display = 'none'
}
else{
fetch("/getDietitians",{
body: JSON.stringify({searchText:searchValue}),
method: "POST",
})
.then((res)=>res.json())
.then((data)=>{
console.log(data)
dietitansFirstLoad.forEach(element=>{
element.style.display = 'none'
})
pagination.style.display = 'none'
if(data.length > 0){
$.each(data,(index,value)=>{
$.each(data,(index1,value1)=>{
$(".all-dietitans-content").append('' +
'<div class="dietitans" data-search="true"><div class="left-image">' +
'<img src="'+value1.photo+'" alt="">' +
'<a onclick="openVideoModal(event)" data-iframe-link="'+value1.video+'">' +
'<i class="far fa-play-circle"></i><br>İzle</a></div><div class="right-content"><div class="dietitans-infos"><div class="left"><div class="name">' +
value1.isim + ' ' + value1.soyisim +
'</div><div class="degree">' +
value1.uzmanlik +
'</div><div class="stars"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i></div></div><div class="right"><div class="item"><div class="title">Yorum Sayısı</div><div class="number">' +
value1.yorum_sayi +
'</div></div><div class="item"><div class="title">Danışan Sayısı</div><div class="number">' +
value1.danisan_sayi +
'</div></div></div></div><div class="dietitans-services-content"><div class="dietitans-description"><div>Uzmanlıklar :</div><div>' +
value1.hizmetler +
'</div></div><div class="buttons-and-text"><div class="buttons"><div class="button-style-2">' +
'<a href="/diyetisyen/'+value1.slug+'">Profili İncele</a>' +
'</div><div class="button-style-1">' +
'<a href="/randevu/'+value1.slug+'">Randevu Al</a>' +
'</div></div></div></div></div></div>')
})
})
}
else{
nullDietitans.style.display = 'block'
document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element=>{
element.remove()
})
}
});
}
}
else{
dietitansFirstLoad.forEach(element=>{
element.style.display = 'flex'
})
pagination.style.display = 'flex'
document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element=>{
element.remove()
})
nullDietitans.style.display = 'none'
}
})
Answers:
It’s because you’re doing multiple queries and |
to combine them, that’s why it is returning duplicates.
instead of doing list = query1 | query2
use Q objects
@csrf_exempt
def getDietitians(request):
from django.http import JsonResponse
if request.method == "POST":
search_str=json.loads(request.body).get('searchText')
from django.db.models import Q
expenses = diyetisyenler.objects.filter(
Q(isim__istartswith=search_str) |
Q(soyisim__istartswith=search_str) |
Q(uzmanlik__icontains=search_str) |
Q(hizmetler__icontains=search_str)
)
data=expenses.values()
return JsonResponse(list(data),safe=False)
Edit
Answer: JS issue, the item list should be removed on every search
And I’ve worked with similar applications, so I’ll drop some ideas I’ve done 🙂
Delay
It might be a good idea to add a delay, so it’s not posting for every single keystroke.
Example: Searching for abc
- Searches for
a
- Searches for
ab
- Searches for
abc
With a delay, I’ve got it at 400 milliseconds, more than likely I’ll just search once for abc
– unless the person types super slow
View
// global unfortunately :(
var interval = 0;
var counter = 0;
$('#inputfield').on('input', function(e) {
if (!$(this).is(':focus')){ return; }
var search = $(this).val().trim();
if (search){
clearInterval(interval);
interval = setInterval(function() {
counter++;
if (counter >= 4){ // 4 * 100 => 400 millisecond delay
clearInterval(interval);
counter = 0;
searchfunction(this);
};
}, 100);
}else{
// Could clear results here
};
};
Ping-Pong Timestamp
Larger Queries will sometimes overwrite smaller ones
Example:
- Send search for
a
(query1) [takes 15 seconds]
- Send search for
absolutely
(query2) [takes 2 seconds]
- query2 returns
- query1 returns, overwriting query2 (not good)
Solution
- On Javascript POST, send
'time': Date.now(),
along with search
- In python return
time
with the results
{'list':list(data), 'time':request.POST.get('time')}
- On Javascript POST return, check if return is newer than rendered
- If newer: updated results & it’s time (time would be any way to store when you sent the search for the what’s rendered)
- If older: just skip the render
I have a django project. In this project, I made a search box with ajax, but the same data is coming more than once. Is the problem in ajax? or is the problem in django? I am not sure. Please help me.
Hey guys.I have a django project. In this project, I made a search box with ajax, but the same data is coming more than once. Is the problem in ajax? or is the problem in django? I am not sure. Please help me.
Hey guys.I have a django project. In this project, I made a search box with ajax, but the same data is coming more than once. Is the problem in ajax? or is the problem in django? I am not sure. Please help me.
my html code
enter code here
<form class="search-content" method="POST">
{% csrf_token %}
<input type="text" name="text" placeholder="Ne Aramıştınız?" id="searchInputChange">
<button>Ara <i class="fas fa-search"></i></button>
</form>
<div class="all-dietitans-content">
<div id="null-search-dietitians">
Aradığınız sonuç bulunamadı. Lütfen aradığınız kelimeyi gözden geçiriniz.
</div>
{% for posts in posts%}
<div class="dietitans" data-firs-load="true">
<div class="left-image">
<img src="{{posts.photo}}" alt="">
<a onclick="openVideoModal(event)" data-iframe-link="{{posts.video}}">
<i class="far fa-play-circle"></i>
<br>
İzle
</a>
</div>
<div class="right-content">
<div class="dietitans-infos">
<div class="left">
<div class="name">
{{posts.isim}} {{posts.soyisim}}
</div>
<div class="degree">
{{posts.uzmanlik}}
</div>
<div class="stars">
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star notStar"></i>
</div>
</div>
<div class="right">
<div class="item">
<div class="title">
Yorum Sayısı
</div>
<div class="number">
{{posts.yorum_sayi}}
</div>
</div>
<div class="item">
<div class="title">
Danışan Sayısı
</div>
<div class="number">
{{posts.danisan_sayi}}
</div>
</div>
</div>
</div>
<div class="dietitans-services-content">
<div class="dietitans-description">
<div>Uzmanlıklar :</div>
<div> {{posts.hizmetler}} </div>
</div>
<div class="buttons-and-text">
<div class="buttons">
<div class="button-style-2">
<a href="{% url 'diyetisyen' slug=posts.slug %}">Profili İncele</a>
</div>
<div class="button-style-1">
<a href="{%url 'randevu' slug=posts.slug %}">Randevu Al</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
my ajax code
enter code here
const nullDietitans = document.getElementById('null-search-dietitians')
const pagination = document.querySelector('.pagination')
const dietitiansContent = document.querySelector(".all-dietitans-content")
const dietitansFirstLoad = document.querySelectorAll('.all-dietitans-content > .dietitans[data-firs-load="true"]')
const searchInputChange=document.querySelector("#searchInputChange");
searchInputChange.addEventListener('input',(e)=>{
nullDietitans.style.display = 'none'
let searchValue=e.target.value.trim();
if(searchValue.length>=3){
if(searchValue === ''){
dietitansFirstLoad.forEach(element=>{
element.style.display = 'flex'
})
pagination.style.display = 'flex'
document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element=>{
element.remove()
})
nullDietitans.style.display = 'none'
}
else{
fetch("/getDietitians",{
body: JSON.stringify({searchText:searchValue}),
method: "POST",
})
.then((res)=>res.json())
.then((data)=>{
console.log(data)
dietitansFirstLoad.forEach(element=>{
element.style.display = 'none'
})
pagination.style.display = 'none'
if(data.length > 0){
$.each(data,(index,value)=>{
$.each(data,(index1,value1)=>{
$(".all-dietitans-content").append('' +
'<div class="dietitans" data-search="true"><div class="left-image">' +
'<img src="'+value1.photo+'" alt="">' +
'<a onclick="openVideoModal(event)" data-iframe-link="'+value1.video+'">' +
'<i class="far fa-play-circle"></i><br>İzle</a></div><div class="right-content"><div class="dietitans-infos"><div class="left"><div class="name">' +
value1.isim + ' ' + value1.soyisim +
'</div><div class="degree">' +
value1.uzmanlik +
'</div><div class="stars"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i></div></div><div class="right"><div class="item"><div class="title">Yorum Sayısı</div><div class="number">' +
value1.yorum_sayi +
'</div></div><div class="item"><div class="title">Danışan Sayısı</div><div class="number">' +
value1.danisan_sayi +
'</div></div></div></div><div class="dietitans-services-content"><div class="dietitans-description"><div>Uzmanlıklar :</div><div>' +
value1.hizmetler +
'</div></div><div class="buttons-and-text"><div class="buttons"><div class="button-style-2">' +
'<a href="/diyetisyen/'+value1.slug+'">Profili İncele</a>' +
'</div><div class="button-style-1">' +
'<a href="/randevu/'+value1.slug+'">Randevu Al</a>' +
'</div></div></div></div></div></div>')
})
})
}
else{
nullDietitans.style.display = 'block'
document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element=>{
element.remove()
})
}
});
}
}
else{
dietitansFirstLoad.forEach(element=>{
element.style.display = 'flex'
})
pagination.style.display = 'flex'
document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element=>{
element.remove()
})
nullDietitans.style.display = 'none'
}
})
It’s because you’re doing multiple queries and |
to combine them, that’s why it is returning duplicates.
instead of doing list = query1 | query2
use Q objects
@csrf_exempt
def getDietitians(request):
from django.http import JsonResponse
if request.method == "POST":
search_str=json.loads(request.body).get('searchText')
from django.db.models import Q
expenses = diyetisyenler.objects.filter(
Q(isim__istartswith=search_str) |
Q(soyisim__istartswith=search_str) |
Q(uzmanlik__icontains=search_str) |
Q(hizmetler__icontains=search_str)
)
data=expenses.values()
return JsonResponse(list(data),safe=False)
Edit
Answer: JS issue, the item list should be removed on every search
And I’ve worked with similar applications, so I’ll drop some ideas I’ve done 🙂
Delay
It might be a good idea to add a delay, so it’s not posting for every single keystroke.
Example: Searching for abc
- Searches for
a
- Searches for
ab
- Searches for
abc
With a delay, I’ve got it at 400 milliseconds, more than likely I’ll just search once for abc
– unless the person types super slow
View
// global unfortunately :(
var interval = 0;
var counter = 0;
$('#inputfield').on('input', function(e) {
if (!$(this).is(':focus')){ return; }
var search = $(this).val().trim();
if (search){
clearInterval(interval);
interval = setInterval(function() {
counter++;
if (counter >= 4){ // 4 * 100 => 400 millisecond delay
clearInterval(interval);
counter = 0;
searchfunction(this);
};
}, 100);
}else{
// Could clear results here
};
};
Ping-Pong Timestamp
Larger Queries will sometimes overwrite smaller ones
Example:
- Send search for
a
(query1) [takes 15 seconds] - Send search for
absolutely
(query2) [takes 2 seconds] - query2 returns
- query1 returns, overwriting query2 (not good)
Solution
- On Javascript POST, send
'time': Date.now(),
along with search - In python return
time
with the results{'list':list(data), 'time':request.POST.get('time')}
- On Javascript POST return, check if return is newer than rendered
- If newer: updated results & it’s time (time would be any way to store when you sent the search for the what’s rendered)
- If older: just skip the render