简体   繁体   English

Django ajax 搜索按钮多条数据

[英]Django ajax search button more than one data

I have a django project.我有一个 django 项目。 In this project, I made a search box with ajax, but the same data is coming more than once.在这个项目中,我用 ajax 做了一个搜索框,但同样的数据不止一次出现。 Is the problem in ajax?是ajax的问题吗? or is the problem in django?还是 django 的问题? I am not sure.我不知道。 Please help me.请帮我。

Hey guys.I have a django project.大家好。我有一个 django 项目。 In this project, I made a search box with ajax, but the same data is coming more than once.在这个项目中,我用 ajax 做了一个搜索框,但同样的数据不止一次出现。 Is the problem in ajax?是ajax的问题吗? or is the problem in django?还是 django 的问题? I am not sure.我不知道。 Please help me.请帮我。

Hey guys.I have a django project.大家好。我有一个 django 项目。 In this project, I made a search box with ajax, but the same data is coming more than once.在这个项目中,我用 ajax 做了一个搜索框,但同样的数据不止一次出现。 Is the problem in ajax?是ajax的问题吗? or is the problem in django?还是 django 的问题? I am not sure.我不知道。 Please help me.请帮我。 my html code我的 html 代码


   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我的 ajax 代码


    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而不是做list = query1 | query2 list = query1 | query2 use Q objects list = query1 | query2使用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回答:JS问题,每次搜索都应该删除项目列表


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示例:搜索abc
  1. Searches for a搜索a
  2. Searches for ab搜索ab
  3. Searches for abc搜索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有延迟,我得到了 400 毫秒,很可能我只会搜索一次abc - 除非这个人打字超级慢

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:例子:
  1. Send search for a (query1) [takes 15 seconds] a搜索 (query1) [需要 15 秒]
  2. Send search for absolutely (query2) [takes 2 seconds]发送absolutely搜索 (query2) [需要 2 秒]
  3. query2 returns查询2返回
  4. query1 returns, overwriting query2 (not good) query1 返回,覆盖 query2(不好)
Solution解决方案
  1. On Javascript POST, send 'time': Date.now(), along with search在 Javascript POST 上,发送'time': Date.now(),以及搜索
  2. In python return time with the results在 python 返回time与结果
    • {'list':list(data), 'time':request.POST.get('time')}
  3. On Javascript POST return, check if return is newer than rendered在 Javascript POST 返回时,检查返回是否比渲染更新
    • 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如果较旧:只需跳过渲染

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM