我尝试使用django-filter显示已过滤的订单列表。每个订单都有一个设备字段,它是一个ForeignKey,如下所示:
class Order(models.Model):
device = models.ForeignKey(Device)
BLACK = 'BLACK'
CYAN = 'CYAN'
MAGENTA = 'MAGENTA'
YELLOW = 'YELLOW'
COLOR_CHOICES = (
(BLACK, 'black'),
(CYAN, 'cyan'),
(MAGENTA, 'magenta'),
(YELLOW, 'yellow'),
)
toner = models.CharField(max_length=200, choices=COLOR_CHOICES)
order_date = models.DateTimeField('order triggered date')
class Meta:
ordering = ['-order_date']
def __str__(self):
return self.toner
默认过滤器类型是ModelChoiceFilter,但它显示了可能数千个设备的很长列表。我希望能够使用CharFilter过滤文本,如下所示:filters.py:
class OrderFilter(df.FilterSet):
device = df.CharFilter(lookup_type='icontains')
order_date = df.DateFilter()
class Meta:
model = Order
fields = ['device', 'toner', 'order_date']
order_by = ['order_date']
但是,在尝试通过设备过滤器字段上的类型文本进行过滤时,我发现了以下错误。
Traceback:
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.4/contextlib.py" in inner
30. return func(*args, **kwds)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
22. return view_func(request, *args, **kwargs)
File "/home/mwood/auto_toner_django/auto_toner/auto_toner/views.py" in OrderView
50. return render(request, 'auto_toner/order_filter.html', context, context_instance=RequestContext(request))
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/shortcuts.py" in render
89. using=using)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/loader.py" in render_to_string
115. template_name, context, context_instance, dirs, dictionary)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/engine.py" in render_to_string
221. return t.render(context_instance)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/base.py" in render
209. return self._render(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/test/utils.py" in instrumented_test_render
96. return self.nodelist.render(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/base.py" in render
903. bit = self.render_node(node, context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/debug.py" in render_node
79. return node.render(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/loader_tags.py" in render
135. return compiled_parent._render(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/test/utils.py" in instrumented_test_render
96. return self.nodelist.render(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/base.py" in render
903. bit = self.render_node(node, context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/debug.py" in render_node
79. return node.render(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/loader_tags.py" in render
65. result = block.nodelist.render(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/base.py" in render
903. bit = self.render_node(node, context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/debug.py" in render_node
79. return node.render(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/endless_pagination/templatetags/endless.py" in render
296. objects = self.objects.resolve(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/base.py" in resolve
787. value = self._resolve_lookup(context)
File "/home/mwood/auto_toner_django/venv_auto_toner/lib/python3.4/site-packages/django/template/base.py" in _resolve_lookup
839. (bit, current)) # missing attribute
Exception Type: VariableDoesNotExist at /devices/orders/
Exception Value: Failed lookup for key [qs] in '<auto_toner.filters.OrderFilter object at 0x7fd721fa32e8>'
知道我做错了什么,或者是否有更好的方法来解决这个问题?感谢
答案 0 :(得分:1)
正如评论中所建议的那样,使用q对象确实变得更简单,并且一旦我花时间去做它就具有更少的依赖性。我实际上从帖子here学到了如何做到这一点,这篇文章描述了用q对象实现一个简单的搜索功能。使用相同的原则从URL中获取请求参数,我很容易想出一个排序/过滤功能。
为了防止链接腐烂,请在此处发布链接内容。
搜索是一种功能,或者至少应该在包含动态或大型内容的大多数网站上展示。
有一些项目可以解决这个问题。这是一个非详尽的清单:djangosearch,django-search(带破折号),django-sphinx。
这些搜索引擎很棒,但如果您只需要CMS或博客的简单搜索功能,那么它们似乎有点过分。
为了解决这个问题,我想出了一个通用而简单的技巧。您只需将以下代码段复制/粘贴到项目中的任何位置:
import re
from django.db.models import Q
def normalize_query(query_string,
findterms=re.compile(r'"([^"]+)"|(\S+)').findall,
normspace=re.compile(r'\s{2,}').sub):
''' Splits the query string in invidual keywords, getting rid of unecessary spaces
and grouping quoted words together.
Example:
>>> normalize_query(' some random words "with quotes " and spaces')
['some', 'random', 'words', 'with quotes', 'and', 'spaces']
'''
return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)]
def get_query(query_string, search_fields):
''' Returns a query, that is a combination of Q objects. That combination
aims to search keywords within a model by testing the given search fields.
'''
query = None # Query to search for every search term
terms = normalize_query(query_string)
for term in terms:
or_query = None # Query to search for a given term in each field
for field_name in search_fields:
q = Q(**{"%s__icontains" % field_name: term})
if or_query is None:
or_query = q
else:
or_query = or_query | q
if query is None:
query = or_query
else:
query = query & or_query
return query
上面的内容是生成一个django.db.models.Q对象(请参阅doc),根据查询字符串和您要搜索的模型字段搜索模型。重要的是,它还通过拆分关键字并允许按引号分组来分析查询字符串。例如,以下查询字符串...
&#39;一些随机的单词&#34;带引号&#34;和空间&#39; ......单词&#39;,&#39;随机&#39;,&#39;单词&#39;,&#39;带引号&#39;,&#39;和&#39;,& #39;空格&#39;实际上会被搜查。它使用所有给定的单词执行AND搜索,但您可以轻松地对其进行自定义以进行不同类型的搜索。
然后,您的搜索视图将变得如此简单:
def search(request):
query_string = ''
found_entries = None
if ('q' in request.GET) and request.GET['q'].strip():
query_string = request.GET['q']
entry_query = get_query(query_string, ['title', 'body',])
found_entries = Entry.objects.filter(entry_query).order_by('-pub_date')
return render_to_response('search/search_results.html',
{ 'query_string': query_string, 'found_entries': found_entries },
context_instance=RequestContext(request))
就是这样!我在一个有大约10,000个新闻项目的网站上使用它,它的工作速度非常快......
现在您没有理由不在您的网站上添加搜索框! ;)