[英]Search in multiple models in Django
我在 Django 中有許多不同的型號,我想在所有型號中搜索關鍵字。 例如,如果您搜索“blah”,我想顯示所有帶有“blah”的產品,所有帶有“blah”的發票,最后是所有其他帶有“blah”的型號。
我可以單獨開發一個視圖並在所有模型中進行搜索,但這不是一個好主意。
這種情況的最佳做法是什么?
我遇到過幾次這種情況,一種解決方案是使用 model 管理器,並為單詞和多詞查詢創建不同的搜索方法。 以下面的示例模型為例: 每個模型都有自己的自定義 Model Manager,具有兩種獨立的查詢方法。 search
將針對所有字段查詢單詞搜索,而search_and
將查詢搜索詞列表中的每個詞,使用reduce
function。兩者都使用Q
對象來完成多字段查找。
from functools import reduce
from django.db.models import Q
class ProductQuerySet(models.QuerySet):
def search(self, query=None):
qs = self
if query is not None:
or_lookup = (Q(product_name__icontains=query) |
Q(description__icontains=query) |
Q(category__icontains=query))
qs = qs.filter(or_lookup, active=True, released=True).distinct()
return qs
def search_and(self, query=None):
qs = self
if query is not None:
or_lookup = reduce(lambda x, y: x & y, [(Q(product_name__icontains=word) |
Q(description__icontains=word) |
Q(category__icontains=word)) for word in query])
qs = qs.filter(or_lookup, active=True, released=True).distinct()
return qs
class ProductManager(models.Manager):
def get_queryset(self):
return ProductQuerySet(self.model, using=self._db)
def search(self, query=None):
return self.get_queryset().search(query=query)
def search_and(self, query=None):
return self.get_queryset().search_and(query=query)
class Product(models.Model):
product_name = models.CharField(max_length=200)
description = models.CharField(max_length=240, blank=True, null=True)
category = models.CharField(max_length=100, choices=CATEGORY)
objects = ProductManager()
def __str__(self):
return self.product_name
class ProfileQuerySet(models.QuerySet):
def search(self, query=None):
qs = self
if query is not None:
or_lookup = (Q(full_name__icontains=query) |
Q(job_title__icontains=query) |
Q(function__icontains=query))
qs = qs.filter(or_lookup, active=True, released=True).distinct()
return qs
def search_and(self, query=None):
qs = self
if query is not None:
or_lookup = reduce(lambda x, y: x & y, [(Q(full_name__icontains=word) |
Q(job_title__icontains=word) |
Q(function__icontains=word)) for word in query])
qs = qs.filter(or_lookup, active=True, released=True).distinct()
return qs
class ProfileManager(models.Manager):
def get_queryset(self):
return ProfileQuerySet(self.model, using=self._db)
def search(self, query=None):
return self.get_queryset().search(query=query)
def search_and(self, query=None):
return self.get_queryset().search_and(query=query)
class Profile(models.Model):
full_name = models.CharField(max_length=200)
job_title = models.CharField(max_length=240, blank=True, null=True)
function = models.CharField(max_length=100, choices=FUNCTION)
objects = ProfileManager()
def __str__(self):
return self.full_name
現在在搜索視圖中使用這些,您可以根據需要指向任意多個 model 經理,它可以查詢任意多個字段。 使用上面的示例模型,下面是一個示例視圖。 它根據術語數(1 個或多於 1 個)將一個或多個搜索術語傳遞給相應的 model 管理器方法。
def application_search(request):
data = dict()
if 'query' in request.GET:
query_list = request.GET.get("query", None).split()
if query_list:
try:
if len(query_list) > 1:
products = Product.objects.search_and(query=query_list)
profiles = Profile.objects.search_and(query=query_list)
else:
products = Product.objects.search(query=query_list[0])
profiles = Profile.objects.search(query=query_list[0])
except:
# Throw exception or log error here
try:
queryset_chain = chain(products, profiles) # combines querysets into one
results = sorted(queryset_chain, key=lambda instance: instance.id, reverse=True) #sorts results by ID
except:
results = None
data['results'] = render_to_string('pages/my_search_result_page.html', {'results': results})
return JsonResponse(data)
此視圖中的query
實際上是通過 AJAX 傳遞到后端的,但是您可以根據您的需要和模板設計進行不同的操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.