Django:不同模型中的全局搜索 - 发布结果不出现

我希望你很好。我在不同的应用程序中创建了一个具有多个模型的全局搜索。

帖子模型属于 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


温温酱
浏览 170回答 3
3回答

梵蒂冈之花

免责声明:这个答案可能不适合OP的观点或模型,但是,它将按原样与示例一起工作。为了清楚起见,我假设我们有两个模型,Musician 它们Album位于sample应用程序中。# sample/models.pyfrom django.db import modelsclass Musician(models.Model):&nbsp; &nbsp; name = models.CharField(max_length=50)&nbsp; &nbsp; def __str__(self):&nbsp; &nbsp; &nbsp; &nbsp; return f'{self.name}'class Album(models.Model):&nbsp; &nbsp; artist = models.ForeignKey(Musician, on_delete=models.CASCADE)&nbsp; &nbsp; name = models.CharField(max_length=100)&nbsp; &nbsp; description = models.TextField()&nbsp; &nbsp; def __str__(self):&nbsp; &nbsp; &nbsp; &nbsp; return f'{self.name} : {self.artist}'然后,我们必须创建一个mixin类,以获得更好的OOP 体验以及跨多个视图的可扩展性。#sample/mixins.pyfrom django.apps import appsfrom django.db.models import Qfrom functools import reducefrom operator import or_class SearchMixin:&nbsp; &nbsp; search_keyword_arg = 'q'&nbsp; &nbsp; search_settings = {}&nbsp; &nbsp; lookup_expr = 'icontains'&nbsp; &nbsp; def get_search_term(self):&nbsp; &nbsp; &nbsp; &nbsp; return self.request.GET.get(self.search_keyword_arg)&nbsp; &nbsp; def build_search_query(self, model_ref, term):&nbsp; &nbsp; &nbsp; &nbsp; return reduce(or_, [Q(**{f'{field}__{self.lookup_expr}': term}) for field in self.search_settings[model_ref]])&nbsp; &nbsp; def get_search_results(self):&nbsp; &nbsp; &nbsp; &nbsp; has_search_result = False&nbsp; &nbsp; &nbsp; &nbsp; search_term = self.get_search_term()&nbsp; &nbsp; &nbsp; &nbsp; if not search_term:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return {'has_search_result': has_search_result}&nbsp; &nbsp; &nbsp; &nbsp; results = {}&nbsp; &nbsp; &nbsp; &nbsp; for model_ref, fields in self.search_settings.items():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; app_name, model_str = model_ref.split('.')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ModelKlass = apps.get_model(app_label=app_name, model_name=model_str)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; qs = ModelKlass.objects.filter(self.build_search_query(model_ref, search_term))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; results[model_ref.replace('.', '_').lower()] = qs&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if has_search_result is False and qs.exists():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; has_search_result = True&nbsp; &nbsp; &nbsp; &nbsp; results['has_search_result'] = has_search_result&nbsp; &nbsp; &nbsp; &nbsp; return results&nbsp; &nbsp; def get_context_data(self, **kwargs):&nbsp; &nbsp; &nbsp; &nbsp; context = super().get_context_data(**kwargs)&nbsp; &nbsp; &nbsp; &nbsp; context['search_result'] = self.get_search_results()&nbsp; &nbsp; &nbsp; &nbsp; return context这个SearchMixin类有我们想要的搜索功能。我们可以将此类添加到任何 Django 视图中来获取结果。为此,我们将SearchMixinclass 继承为ListViewas,# sample/views.pyfrom django.views.generic import TemplateViewfrom sample.mixins import SearchMixinclass GlobalSearchView(SearchMixin, TemplateView):&nbsp; &nbsp; template_name = 'sample/global_search.html'&nbsp; &nbsp; search_settings = {&nbsp; &nbsp; &nbsp; &nbsp; 'sample.Musician': ['name'],&nbsp; &nbsp; &nbsp; &nbsp; 'sample.Album': ['name', 'description'],&nbsp; &nbsp; }笔记:我使用了TemplateView更适合这种特殊情况的方法。有一个名为的新类属性search_settings,用于确定搜索字段。search_settings属性应该如何?它必须是一个dict(或dict类似的对象)对象的键dict应该采用以下app_name.ModelClassName格式的值dict必须是模型字段的可迭代它在模板中看起来怎么样?该类SearchMixin将搜索结果添加到名为 and 的上下文变量中,search_result该变量还有另一个变量has_search_result(&nbsp;search_result.has_search_result),可用于检查我们是否有“任何匹配”。此外,每个查询集都可以通过单独的变量访问。变量的格式为,&nbsp;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 %}&nbsp; &nbsp; <strong>Musician result</strong><br>&nbsp; &nbsp; {% for musician in search_result.sample_musician %}<br>&nbsp; &nbsp; &nbsp; &nbsp; {{ musician.name }}&nbsp; &nbsp; {% endfor %}&nbsp; &nbsp; <br><br>&nbsp; &nbsp; <strong>Album result</strong><br>&nbsp; &nbsp; {% for album in search_result.sample_album %}&nbsp; &nbsp; &nbsp; &nbsp; {{ album.name }} -- {{ album.description }}<br>&nbsp; &nbsp; {% endfor %}{% else %}&nbsp; &nbsp; No match{% endif %}现在,连接视图urls.py并使用查询参数进行搜索,如下所示:/foo-bar/global-search/?q=xx

元芳怎么了

我认为最好将所有内容都get_context_data这样放入:&nbsp;# global search&nbsp;class GlobalSearchView(ListView):&nbsp; &nbsp; template_name = 'search_global.html'&nbsp; &nbsp; count = 0&nbsp; &nbsp; countnutri = 0&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; def get_context_data(self, *args, **kwargs):&nbsp; &nbsp; &nbsp; &nbsp; context = super().get_context_data(*args, **kwargs)&nbsp; &nbsp; &nbsp; &nbsp; context['count'] = self.count or 0&nbsp; &nbsp; &nbsp; &nbsp; context['countnutri'] = self.countnutri or 0&nbsp; &nbsp; &nbsp; &nbsp; query = self.request.GET.get('q', None)&nbsp; &nbsp; &nbsp; &nbsp; context['query'] = query&nbsp; &nbsp; &nbsp; &nbsp; if query:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nutriscore = Post.objects.filter(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 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)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ).distinct()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; user = UserProfile.objects.filter(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 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)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ).distinct()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context['results'] = chain(nutriscore,user)&nbsp; &nbsp; &nbsp; &nbsp; return contextresults然后您可以在模板中使用变量

精慕HU

你有 3 个 return 语句,所以只有第一个会被执行: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;qs&nbsp;&nbsp;#&nbsp;return&nbsp;user &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;qn&nbsp;&nbsp;#&nbsp;return&nbsp;nutriscore&nbsp;/&nbsp;NOT&nbsp;EXECUTED &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;results&nbsp;&nbsp;#&nbsp;return&nbsp;results&nbsp;/&nbsp;NOT&nbsp;EXECUTED你应该只保留return results.如果您确实想返回 3 个项目,请以元组形式返回:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;qa,&nbsp;qn,&nbsp;results
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python