簡體   English   中英

如何根據 django-rest-framework 中的最佳匹配對查詢集進行排序?

[英]How to order queryset based on best match in django-rest-framework?

我正在嘗試按匹配數對帶有參數的查詢結果進行排序

例如,假設我們有一個模型:

class Template(models.Model):
    headline = CharField(max_length=300)
    text = TextField()
    image_text = TextField(max_length=500, blank=True, null=True)
    tags = TaggableManager(through=TaggedItem)
    ...

使用序列化程序:

class TemplateSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Template
        fields = (...)

和一個視圖集:

class TemplateViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows Templates to be viewed or edited.
    """
    queryset = Template.objects.all()
    serializer_class = TemplateSerializer

    def get_queryset(self):
        queryset = Template.objects.all()

        tags = self.request.query_params.getlist('tags', None)
        search_text = self.request.query_params.getlist('search_text', None)

        if tags is not None:
            queries = [Q(groost_tags__name__iexact=tag) for tag in tags]
            query = queries.pop()
            for item in queries:
                query |= item

            queryset = queryset.filter(query).distinct()

        if search_tags is not None:
            queries = [Q(image_text__icontains=string) |
                       Q(text__icontains=string) |
                       Q(headline__icontains=string) for string in search_tags]
            query = queries.pop()
            for item in queries:
                query |= item

            queryset = queryset.filter(query).distinct()

我需要做的是計算過濾器找到的每個匹配項,然后按每個模板的匹配項數對查詢集進行排序。 例如:

我想找到所有在文本、圖像文本或標題中包含“hello”“world”字符串的模板。 所以我將查詢參數“search_text”設置hello,world 帶有標題 =“世界文本 =“大家,大家”的模板 將有2 場比賽 另一個標題為“你好”的將有1 個匹配項 具有 2 個匹配項的模板將是查詢集中的第一個模板。 相同的行為應該適用於帶有search_text組合的標簽標簽

我試圖在 ViewSet 中計算這些數字,然后返回一個sorted(queryset, key=attrgetter('matches'))但遇到了 DRF 的幾個問題,比如Template 沒有屬性“matches”。 或者通過 API 直接訪問 Template 實例時出現 404。

有任何想法嗎?

嘗試annotation ,其中每個匹配對返回 1 或 0,並匯總為排名:

from django.db.models import Avg, Case, F, FloatField, Value, When

Template.objects.annotate(
    k1=Case(
        When(image_text__icontains=string, then=Value(1.0)),
        default=Value(0.0),
        output_field=FloatField(),
    ),
    k2=Case(
        When(text__icontains=string, then=Value(1.0)),
        default=Value(0.0),
        output_field=FloatField(),
    ),
    k3=Case(
        When(headline__icontains=string, then=Value(1.0)),
        default=Value(0.0),
        output_field=FloatField(),
    ),
    rank=F("k1") + F("k2") + F("k3"),
).order_by("-rank")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM