首页 > 解决方案 > Django Views 和 Javascript 函数之间的连接

问题描述

我目前正在设置我的 Django 项目,它是一个搜索引擎,我一直在尝试在自定义 Django 视图和 Javascript 函数之间建立连接,但我一直遇到问题,所以我决定从头开始重新启动它,并希望得到某人的帮助。

我有这个 Javascript 代码

const data = []  // Not sure how to get the data from the backend??

let index = 0;
let results = [];
const randomSearchMatchPercentages = ( array ) => {
    for ( const element of array ) {
        // define a maximum and a minimum range
        const maximum = index <= 100 ? 100 - index : 0;
        const minimum = maximum > 0 ? maximum - 5 : 0;

        element.match = Math.round( Math.random() * ( maximum - minimum ) + minimum ) + "%";
        results.push( element );

        // decrease the maximum and minimum for the next iteration
        index += 5;
    }
console.log( results );
}

randomSearchMatchPercentages( data );

我需要像这样连接自定义视图:

def MatchingScore(request):

    return JsonResponse(output)

我已经建立了一个连接并从后端获取数据以使用此视图自动完成:

def autocomplete(request):
    sqs = SearchQuerySet().autocomplete(
        content_auto=request.GET.get('query',''))[:5]
    destinations = {result.destination for result in sqs}
    s = [{"value": dest, "data": dest} for dest in destinations]
    output = {'suggestions': s}
    return JsonResponse(output)

并使用此 Javascript 函数:

$(function () {
    'use strict';

    $('#q').autocomplete({
    serviceUrl: "http://127.0.0.1:8000/search/autocomplete/",
    minChars: 2,
    dataType: 'json',
    type: 'GET',
    onSelect: function (suggestion) {
        console.log( suggestion.value + ', data :' + suggestion.data);
    }
});

});

但我不知道要在我的内部放入什么代码def MatchingScore以及如何调整 Javascript 代码以使其工作。我假设我需要以与我相同的方式从我的数据库中获取数据autocomplete View并将其传递给 javascript 函数。

我的目标非常简单:生成 100% 到 0% 之间的随机数并将其显示到一个 html 列表中,如下所示:

<div>
{% if  page_obj.object_list %}
      <ol class="row top20">

        {% for result in page_obj.object_list %}

     <li class="list-item">
      <div class="showcase col-sm-6 col-md-4">
           <a href="{{ result.object.get_absolute_url }}">
              <h3>{{result.object.title}}</h3>
              <img src="{{ result.object.image }}" class="img-responsive">
           </a>
      </div>
     <li>

         {% endfor %}
      </ol>
</div>

{% else %}
        <p> Sorry, no result found </p>
{% endif %}

我怎样才能做到这一点?

编辑:

我有这个与 Django-Haystack 一起用于搜索功能的自定义 forms.py 文件:

from haystack.forms import FacetedSearchForm


class FacetedProductSearchForm(FacetedSearchForm):

    def __init__(self, *args, **kwargs):
        data = dict(kwargs.get("data", []))
        self.ptag = data.get('ptags', [])
        super(FacetedProductSearchForm, self).__init__(*args, **kwargs)

    def search(self):
        sqs = super(FacetedProductSearchForm, self).search()

        if self.ptag:
            query = None
            for ptags in self.ptag:
                if query:
                    query += u' OR '
                else:
                    query = u''
                query += u'"%s"' % sqs.query.clean(ptags)
            sqs = sqs.narrow(u'ptags_exact:%s' % query)

        return sqs

然后我通过这个类将自定义表单传递到我的视图中:

from haystack.generic_views import FacetedSearchView as BaseFacetedSearchView
from .forms import FacetedProductSearchForm

class FacetedSearchView(BaseFacetedSearchView):

    form_class = FacetedProductSearchForm
    facet_fields = ['ptags']
    template_name = 'search_result.html'
    paginate_by = 20
    context_object_name = 'object_list'

我已经尝试了第一种方法,但我没有得到任何搜索结果,并且由于我已经有了paginationand object_name,有没有办法通过缩进或其他方式来实现该类def MatchingScoredef random_search_match_percentages该类,以便我可以调用在match这个模板标签内?:

{% if  page_obj.object_list %}

        {% for result in page_obj.object_list %}

         {% endfor %}

{% else %}

{% endif %}

标签: javascriptpythonhtmldjango

解决方案


如果我正确理解问题,我认为你有两种不同的方法来实现你想要在这里实现的目标。

一种方法是:您可以将要运行的 Javascript 代码转换为 Python 代码(因为它不执行任何特定的 JavaScript 操作,例如处理 DOM),并MatchingScore通过传递您想要的数据来调用它,就像您使用autocomplete功能。

from django.shortcuts import render
from django.core.paginator import Paginator


def random_search_match_percentages(array):
    from random import random
    from math import floor

    index = 0
    results = []

    for element in array:
        # define a maximum and a minimum range
        maximum = 100 - index if index <= 100 else 0
        minimum = maximum - 5 if maximum > 0 else 0

        num = floor(random() * (maximum - minimum) + minimum + 0.5)
        element.match = '{}%'.format(num)  # add the match param
        results.append(element)

        # decrease the maximum and minimum for the next iteration
        index += 5

    return results


# small tip: this naming convention you are using is generally used
# for python classes, not function. Generally python developers
# write function names using snake case, like this: matching_score
def MatchingScore(request):
    some_data = MyModel.objects.all()  # just an example of grabbing data...
    paginator = Paginator(some_data, per_page=20)
    page_obj = paginator.get_page(page)

    results = random_search_match_percentages(page_obj)

    return render(request, 'my_app/my_view.html', {'results': results})

然后,您可以访问其中的数据,my_view.html就像您的 Django 模板代码片段一样。

在您的应用模板文件夹中创建一个my_view.html文件,即:django_project/my_app/templates/my_app/my_view.html使用以下内容:

<div>
{% if results|length %}
  <ol class="row top20">
    {% for result in results %}
      <li class="list-item">
        <div class="showcase col-sm-6 col-md-4">
           <a href="{% url 'some-product-url' result.django_id %}">
            <h3>{{ result.title }}</h3>
              <!-- use the match param added on the
              random_search_match_percentages function -->
              <p>{{ result.match }}</p>
              <img src="{{ result.image }}" class="img-responsive">
           </a>
        </div>
      </li>
  {% endfor %}
  </ol>
{% else %}
  <p>Sorry, no result found</p>
{% endif %}
</div>

另一种方法是:

1) 制作一个 django 视图,返回您想要的 JSON 数据(例如autocomplete视图)

def matching_score_data(request):
    # grab your data...
    return JsonResponse(data)

2)然后,做一个简单的视图

from django.shortcuts import render


def MatchingScore(request):
    return render(request, 'my_app/my_view.html')

3) 然后,将您的 JavaScript 代码放在 `my_view.html 中。对于数据,您可以进行 AJAX 调用来获取它。渲染列表。您将需要使用 JavaScript 操作 DOM。

<ol class="row top20" id="my_list">
</ol>

<script>
$(function () {
    'use strict';

    const randomSearchMatchPercentages = array => {
        let index = 0;
        let results = [];

        for (const element of array) {
            // define a maximum and a minimum range
            const maximum = index <= 100 ? 100 - index : 0;
            const minimum = maximum > 0 ? maximum - 5 : 0;

            element.match = Math.round( Math.random() * ( maximum - minimum ) + minimum ) + "%";
            results.push(element);

            // decrease the maximum and minimum for the next iteration
            index += 5;
        }
        return results;
    }

    $.get("/matching_score_data", function(data) {
        // randomSearchMatchPercentages function in here...
        const results = randomSearchMatchPercentages(data);

        // now, to show the list you need to manipulate
        // the DOM appending the elements inside the
        // #my_list ol element
        for (let i = 0; i < data.length; i++) {
            $("#my_list ol").append(`
                <li class="list-item">
                    <div class="showcase col-sm-6 col-md-4">
                        <a href="${results[i].url}">
                            <h3>${results[i].title}</h3>
                            <p>${results[i].match}</p>
                            <img src="${results[i].image}" class="img-responsive">
                        </a>
                    </div>
                </li>
            `);
        }
    });
});
</script>

恕我直言:我认为第一种方法更简单,因为您拥有 django 模板引擎的强大功能,并且不需要使用 javascript 操作 DOM。此外,您只需要创建一个视图而不是两个。

参考:


推荐阅读