我的应用程序-基础知识

我有一个简单的Django应用程序,它允许存储有关某些物品的信息,我正在try 实现一个搜索视图/功能.

我使用django-taggit来根据它们的功能/特性来标记这些项目.

我想要实施的是

我想实现一个全文搜索,允许搜索在所有领域的项目,包括他们的标签.

《问题》(S)

  1. 在结果视图上,标记的项目会多次出现(每个标记出现一次)
  2. 当我在搜索字段中只指定*单个*标签时,排名是正确的,但当我指定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()

推荐答案

您的问题是直接将标记字段添加到您的SearchVector

让我们将带有Django‘s StringAgg的标记连接成一个字符串,然后在SearchVector中使用该字符串

首先,我们进口StringAgg

from django.contrib.postgres.aggregates import StringAgg

那么这就是你必须改变你的get_queryset功能的方法

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 queryset

        queryset = queryset.annotate(tags_str=StringAgg('tags__name', delimiter=' '))
        search_vector = SearchVector('identifier', 'short_text', 'serial_number', 'revision', 'part_number',
                                     'manufacturer', 'description', 'tags_str')
        search_query = SearchQuery(form.cleaned_data['search'], search_type='websearch')
        return (
            queryset.annotate(
                search=search_vector, rank=SearchRank(search_vector, search_query)
            )
            .order_by("-rank").distinct()
        )
    return queryset

Python相关问答推荐

不同数据类型的Python成员变量不会在具有相同优先级的不同线程中更新

try 使用tensorFlow.keras.models时optree Import错误

使用Python OpenCV的文本检测分割

无法导入已安装的模块

机器人与Pyton Minecraft服务器状态不和

Matplotlib轮廓线值似乎不对劲

将numpy矩阵映射到字符串矩阵

配置Sweetviz以分析对象类型列,而无需转换

比较两个数据帧并并排附加结果(获取性能警告)

使用numpy提取数据块

Deliveryter Notebook -无法在for循环中更新matplotlib情节(保留之前的情节),也无法使用动画子功能对情节进行动画

韦尔福德方差与Numpy方差不同

带条件计算最小值

使用miniconda创建环境的问题

如何制作10,000年及以后的日期时间对象?

有没有一种方法可以从python的pussompy比较结果中提取文本?

关于Python异步编程的问题和使用await/await def关键字

Pandas:计算中间时间条目的总时间增量

并行编程:同步进程

Python pint将1/华氏度转换为1/摄氏度°°