javascript - 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'
我已经尝试了第一种方法,但我没有得到任何搜索结果,并且由于我已经有了pagination
and object_name
,有没有办法通过缩进或其他方式来实现该类def MatchingScore
和def random_search_match_percentages
该类,以便我可以调用在match
这个模板标签内?:
{% if page_obj.object_list %}
{% for result in page_obj.object_list %}
{% endfor %}
{% else %}
{% endif %}
解决方案
如果我正确理解问题,我认为你有两种不同的方法来实现你想要在这里实现的目标。
一种方法是:您可以将要运行的 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。此外,您只需要创建一个视图而不是两个。
参考: