我的应用程序-基础知识
我有一个简单的Django应用程序,它允许存储有关某些物品的信息,我正在try 实现一个搜索视图/功能.
我使用django-taggit
来根据它们的功能/特性来标记这些项目.
我想要实施的是
我想实现一个全文搜索,允许搜索在所有领域的项目,包括他们的标签.
《问题》(S)
- 在结果视图上,标记的项目会多次出现(每个标记出现一次)
- 当我在搜索字段中只指定*单个*标签时,排名是正确的,但当我指定multiple个标签名称时,我会得到意想不到的排名结果.
我怀疑SearchVector()
没有像我预期的那样解析标记关系.在本例中,应将标记视为单词列表.
示例代码
Models.py
from django.db import models
from taggit.managers import TaggableManager
class Item(models.Model):
identifier = models.SlugField('ID', unique=True, editable=False)
short_text = models.CharField('Short Text', max_length=100, blank=True)
serial_number = models.CharField('Serial Number', max_length=30, blank=True)
revision = models.CharField('Revision/Version', max_length=30, blank=True)
part_number = models.CharField('Part Number', max_length=30, blank=True)
manufacturer = models.CharField('Manufacturer', max_length=30, blank=True)
description = models.TextField('Description', blank=True)
tags = TaggableManager('Tags', blank=True)
is_active = models.BooleanField('Active', default=True)
Forms.py
from django import forms
class SearchForm(forms.Form):
search = forms.CharField(max_length=200, required=False)
active_only = forms.BooleanField(initial=True, label='Show active items only', required=False)
Views.py
from django.views.generic.list import ListView
from django.contrib.postgres.search import SearchQuery, SearchVector, SearchRank
from . import models
from . import forms
class ItemListView(ListView):
form_class = forms.SearchForm
model = models.Item
fields = ['serial_number', 'part_number', 'manufacturer', 'tags', 'is_active']
template_name_suffix = '_list'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = self.form_class(self.request.GET)
return context
def get_queryset(self):
queryset = super().get_queryset()
form = self.form_class(self.request.GET)
if form.is_valid():
if form.cleaned_data['active_only']:
queryset = queryset.filter(is_active=True)
if not form.cleaned_data['search']:
return super().get_queryset()
search_vector = SearchVector('identifier', 'short_text', 'serial_number', 'revision', 'part_number',
'manufacturer', 'description', 'tags')
search_query = SearchQuery(form.cleaned_data['search'], search_type='websearch')
return (
queryset.annotate(
search=search_vector, rank=SearchRank(search_vector, search_query)
)
# .filter(search=search_query)
.order_by("-rank").distinct()
) #.filter(search__icontains=form.cleaned_data['search'],)
return super().get_queryset()