这种功能通常称为"自动完成"(autocomplete)或"搜索建议"(search suggestion),它结合了以下技术:
首先创建一个视图处理搜索请求:
# views.py
from django.http import JsonResponse
from django.db.models import Q
from yourapp.models import YourModel
def search_view(request):
query = request.GET.get('q', '')
results = YourModel.objects.filter(
Q(name__icontains=query) |
Q(description__icontains=query)
)[:10] # 限制返回结果数量
data = [{
'id': item.id,
'name': item.name,
'url': item.get_absolute_url() # 确保模型有这个方法
} for item in results]
return JsonResponse(data, safe=False)
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('search/', views.search_view, name='search'),
]
<!-- 在模板文件中 -->
<input type="text" id="search-input" placeholder="搜索...">
<div id="search-results"></div>
<script>
document.getElementById('search-input').addEventListener('input', function(e) {
const query = e.target.value;
if (query.length < 2) { // 至少输入2个字符才搜索
document.getElementById('search-results').innerHTML = '';
return;
}
fetch(`/search/?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(data => {
const resultsContainer = document.getElementById('search-results');
if (data.length > 0) {
let html = '<ul class="search-dropdown">';
data.forEach(item => {
html += `<li><a href="${item.url}">${item.name}</a></li>`;
});
html += '</ul>';
resultsContainer.innerHTML = html;
} else {
resultsContainer.innerHTML = '<div class="no-results">无结果</div>';
}
});
});
</script>
#search-results {
position: relative;
}
.search-dropdown {
position: absolute;
z-index: 1000;
width: 100%;
max-height: 300px;
overflow-y: auto;
background: white;
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
list-style: none;
padding: 0;
margin: 0;
}
.search-dropdown li a {
display: block;
padding: 8px 12px;
color: #333;
text-decoration: none;
}
.search-dropdown li a:hover {
background-color: #f5f5f5;
}
.no-results {
padding: 8px 12px;
color: #666;
}
问题:用户快速输入时发送过多请求
解决:添加防抖(debounce)功能
function debounce(func, wait) {
let timeout;
return function() {
const context = this, args = arguments;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
document.getElementById('search-input').addEventListener('input', debounce(function(e) {
// 搜索逻辑
}, 300)); // 300毫秒延迟
问题:搜索结果排序不理想
解决:在后端添加更复杂的排序逻辑
results = YourModel.objects.filter(
Q(name__icontains=query) | Q(description__icontains=query)
).annotate(
name_match=Case(
When(name__istartswith=query, then=Value(1)),
default=Value(0),
output_field=IntegerField()
)
).order_by('-name_match', 'name')[:10]
问题:可能受到XSS攻击
解决:在前端转义HTML
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
// 使用方式
html += `<li><a href="${escapeHtml(item.url)}">${escapeHtml(item.name)}</a></li>`;
这个实现提供了完整的端到端解决方案,可以根据具体需求进行调整和扩展。
没有搜到相关的文章