亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Django:不同模型中的全局搜索 - 發布結果不出現

Django:不同模型中的全局搜索 - 發布結果不出現

溫溫醬 2023-06-27 13:58:16
我希望你很好。我在不同的應用程序中創建了一個具有多個模型的全局搜索。帖子模型屬于 Nutriscore 文件夾UserProfile 模型屬于 User 文件夾如果我使用一個涵蓋帖子和用戶配置文件搜索的單詞,例如主課程。我得到了 UserProfile 的一些搜索結果(3 個結果),但 Post 沒有出現任何內容(而count給了我 6 個結果)。所以我不知道代碼有什么問題?用戶/視圖.py# global search class GlobalSearchView(ListView):    template_name = 'search_global.html'    count = 0    countnutri = 0        def get_context_data(self, *args, **kwargs):        context = super().get_context_data(*args, **kwargs)        context['count'] = self.count or 0        context['countnutri'] = self.countnutri or 0        context['query'] = self.request.GET.get('q')        return context        def get_queryset(self): # new        query = self.request.GET.get('q', None)        if query is not None:            nutriscore = Post.objects.filter(                Q(title__icontains=query) | Q(slug__icontains=query) | Q(typederepas__name__icontains=query) | Q(prixrepas__name__icontains=query) | Q(vitesserepas__name__icontains=query) | Q(force__name__icontains=query) | Q(bienfaitrepas__name__icontains=query)            ).distinct()            user = UserProfile.objects.filter(                Q(pays__icontains=query) | Q(town__icontains=query) | Q(user__username__icontains=query) | Q(mealtrend__name__icontains=query) | Q(pricetrend__name__icontains=query) | Q(speedtrend__name__icontains=query)| Q(strengthtrend__name__icontains=query) | Q(wellnesstrend__name__icontains=query)            ).distinct()            results = chain(nutriscore,user)                        qs = sorted(user,                         key=lambda instance: instance.pk,                         reverse=True)            self.count = len(qs)                        qn = sorted(nutriscore,                         key=lambda instance: instance.pk,                         reverse=True)            self.countnutri = len(qn)                        return qs            return qn            return results
查看完整描述

3 回答

?
梵蒂岡之花

TA貢獻1900條經驗 獲得超5個贊

免責聲明:這個答案可能不適合OP的觀點或模型,但是,它將按原樣與示例一起工作。


為了清楚起見,我假設我們有兩個模型,Musician 它們Album位于sample應用程序中。


# sample/models.py


from django.db import models



class Musician(models.Model):

    name = models.CharField(max_length=50)


    def __str__(self):

        return f'{self.name}'



class Album(models.Model):

    artist = models.ForeignKey(Musician, on_delete=models.CASCADE)

    name = models.CharField(max_length=100)

    description = models.TextField()


    def __str__(self):

        return f'{self.name} : {self.artist}'

然后,我們必須創建一個mixin類,以獲得更好的OOP 體驗以及跨多個視圖的可擴展性。


#sample/mixins.py


from django.apps import apps

from django.db.models import Q

from functools import reduce

from operator import or_



class SearchMixin:

    search_keyword_arg = 'q'

    search_settings = {}

    lookup_expr = 'icontains'


    def get_search_term(self):

        return self.request.GET.get(self.search_keyword_arg)


    def build_search_query(self, model_ref, term):

        return reduce(or_, [Q(**{f'{field}__{self.lookup_expr}': term}) for field in self.search_settings[model_ref]])


    def get_search_results(self):

        has_search_result = False

        search_term = self.get_search_term()

        if not search_term:

            return {'has_search_result': has_search_result}


        results = {}


        for model_ref, fields in self.search_settings.items():

            app_name, model_str = model_ref.split('.')

            ModelKlass = apps.get_model(app_label=app_name, model_name=model_str)

            qs = ModelKlass.objects.filter(self.build_search_query(model_ref, search_term))

            results[model_ref.replace('.', '_').lower()] = qs

            if has_search_result is False and qs.exists():

                has_search_result = True


        results['has_search_result'] = has_search_result

        return results


    def get_context_data(self, **kwargs):

        context = super().get_context_data(**kwargs)

        context['search_result'] = self.get_search_results()

        return context

這個SearchMixin類有我們想要的搜索功能。我們可以將此類添加到任何 Django 視圖中來獲取結果。


為此,我們將SearchMixinclass 繼承為ListViewas,


# sample/views.py


from django.views.generic import TemplateView

from sample.mixins import SearchMixin



class GlobalSearchView(SearchMixin, TemplateView):

    template_name = 'sample/global_search.html'

    search_settings = {

        'sample.Musician': ['name'],

        'sample.Album': ['name', 'description'],

    }

筆記:

  • 我使用了TemplateView適合這種特殊情況的方法。

  • 有一個名為的新類屬性search_settings,用于確定搜索字段。

search_settings屬性應該如何?

  • 它必須是一個dict(或dict類似的對象)

  • 對象的鍵dict應該采用以下app_name.ModelClassName格式

  • 的值dict必須是模型字段的可迭代

它在模板中看起來怎么樣?
該類SearchMixin將搜索結果添加到名為 and 的上下文變量中,search_result該變量還有另一個變量has_search_resultsearch_result.has_search_result),可用于檢查我們是否有“任何匹配”

此外,每個查詢集都可以通過單獨的變量訪問。變量的格式為, app_name<underscore><model_name_in_lower_case>.

例如,對于模型,可以在模板中sample.Musician獲取搜索結果(如果有),如下所示:{{ search_result.sample_musician }}

# sample/templates/sample/global_search.html


{% if search_result.has_search_result %}

    <strong>Musician result</strong><br>

    {% for musician in search_result.sample_musician %}<br>

        {{ musician.name }}

    {% endfor %}

    <br><br>

    <strong>Album result</strong><br>

    {% for album in search_result.sample_album %}

        {{ album.name }} -- {{ album.description }}<br>

    {% endfor %}

{% else %}

    No match

{% endif %}

現在,連接視圖urls.py并使用查詢參數進行搜索,如下所示:


/foo-bar/global-search/?q=xx




查看完整回答
反對 回復 2023-06-27
?
元芳怎么了

TA貢獻1798條經驗 獲得超7個贊

我認為最好將所有內容都get_context_data這樣放入:


 # global search 

class GlobalSearchView(ListView):

    template_name = 'search_global.html'

    count = 0

    countnutri = 0

    

    def get_context_data(self, *args, **kwargs):

        context = super().get_context_data(*args, **kwargs)

        context['count'] = self.count or 0

        context['countnutri'] = self.countnutri or 0

        query = self.request.GET.get('q', None)

        context['query'] = query

        if query:

            nutriscore = Post.objects.filter(

                Q(title__icontains=query) | Q(slug__icontains=query) | Q(typederepas__name__icontains=query) | Q(prixrepas__name__icontains=query) | Q(vitesserepas__name__icontains=query) | Q(force__name__icontains=query) | Q(bienfaitrepas__name__icontains=query)

            ).distinct()

            user = UserProfile.objects.filter(

                Q(pays__icontains=query) | Q(town__icontains=query) | Q(user__username__icontains=query) | Q(mealtrend__name__icontains=query) | Q(pricetrend__name__icontains=query) | Q(speedtrend__name__icontains=query)| Q(strengthtrend__name__icontains=query) | Q(wellnesstrend__name__icontains=query)

            ).distinct()

            context['results'] = chain(nutriscore,user)

        return context

results然后您可以在模板中使用變量


查看完整回答
反對 回復 2023-06-27
?
精慕HU

TA貢獻1845條經驗 獲得超8個贊

你有 3 個 return 語句,所以只有第一個會被執行:

            return qs  # return user
            return qn  # return nutriscore / NOT EXECUTED
            return results  # return results / NOT EXECUTED

你應該只保留return results.

如果您確實想返回 3 個項目,請以元組形式返回:

            return qa, qn, results


查看完整回答
反對 回復 2023-06-27
  • 3 回答
  • 0 關注
  • 210 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號