在 Django 中预先输入返回对象计数而不是可选字符串

问题描述

我正在尝试为我的应用程序实现 typeahead.js。我跟进了以下一些示例 stackoverflowTwitter typeahead official doc。我创建了一个运行良好的 Django Rest API,我还能够让 typeahead 弹出建议。在所有这些之后,我面临着两个我自己无法解决的困难。第一个是脚本返回的不是显示字符串结果,而是返回总对象计数

see screenshot

,而第二个问题是无法选择弹出建议。

有没有办法解决这些问题?

main.js

//live search
$(document).ready(function(){
    var searchResults = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('lead'),queryTokenizer: Bloodhound.tokenizers.whitespace,prefetch: '../auth/api/data/',remote: {
            url: "/auth/api/data/",wildcard: '%QUERY',}
    });

    $('.typeahead').typeahead(null,{
            name: 'leads-display',display: 'lead',source: searchResults,templates: {
                empty: [
                      '<div class="empty-message">','No user found','</div>'
                ].join('\n'),suggestion: function(data){
                    return '<div class="live-search-results">'
                    + '<strong>' + data + '</strong>'
                    + '</div>';
                }
            }
        }
    );
});

解决方法

我找到了解决问题的方法。我做的第一件事是丢弃了我的 DRF API,因为我面临着太多的问题。因此,我在 JSON 中创建了一个 views.py 视图,而不是 REST API,如下所示

    def get_leads(request):
        results = []
        lead = request.GET.get('lead')
        users = User.objects.filter(name__icontains=lead)
        data = [{'id': user.pk,'name': user.name,'avatar': user.avatar,'email': user.email} for user in users]
        return JsonResponse(data,encoder=ExtendedEncoder,safe=False)

我还确保使用 simplejson 序列化我的 FileField,因为我想在搜索结果中显示图像。 encoder.py

from django.core.serializers.json import DjangoJSONEncoder
from django.db.models.fields.files import FieldFile

# custom JSON encoder for FieldFile
class ExtendedEncoder(DjangoJSONEncoder):
    def default(self,obj):
        if isinstance(obj,FieldFile):
            return str(obj)
        return super(ExtendedEncoder,self).default(obj)

最后,在我的 .js 文件中,我执行了以下操作

    $(document).ready(function(){
    var substringMatcher = function(strings) {
        return function findMatches(q,cb) {
        var data,substringRegex;
        // an array that will be populated with substring matches
        matches = [];
        // regex used to determine if a string contains the substring `q`
        substringRegex = new RegExp(q,'i');
        // iterate through the pool of strings and for any string that
        // contains the substring `q`,add it to the `matches` array
        $.each(strings,function(i,string) {
          if (substringRegex.test(string)) {
            matches.push(string);
          }
        });
        cb(matches);
        };
    };

    var leads = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),queryTokenizer: Bloodhound.tokenizers.whitespace,remote: {
            url: '/xxx/xxxx/?lead=%QUERY',wildcard: '%QUERY'
        }
    });

    $('#remote .typeahead').typeahead({
        hint: true,highlight: true,minLength: 1,},{
        name: 'lead',limit: 15,display: 'name',source: leads,templates: {
             empty: [
                  '<div class="empty-message">','No user found','</div>'
            ].join('\n'),suggestion: function(data){
                console.log(data) //print result as a json object in console log
                var spanId = data.name.toLowerCase().replace(/\s/g,'');
                return '<div class="live-search-results">'
                + '<span class="input-field-live-search-result"' + 'id="'+ spanId +'">'
                + '<img class="live-search-image"' + 'src="/media/' + data.avatar + '"' + 'alt="'
                + data.name + "'s avatar" + '"' + 'width="25px" height="25px" />' + data.name + ' - ' + data.email
                + '</span> </div>';
            },}
    });
  });

我希望这可以帮助任何面临或可能面临类似问题的人。