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_result
( search_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

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然后您可以在模板中使用變量

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
添加回答
舉報