使用 Django 过滤器搜索

sur*_*itM 5 django filter

我正在尝试对姓名和电子邮件字段执行搜索。对于电子邮件字段,它给出了一个错误“int() 的无效文字,基数为 10:'abc@xyz.com'”。但是当我使用 user.id 时,它给出了正确的结果。对于名称字段,它给出了无法将关键字 'first_name' 解析为字段。我如何让它工作。任何帮助将不胜感激。我的两个模型是:

class publication(models.Model):
    title = models.CharField(max_length=500)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
    ....

class MyUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(_('email address'), max_length=254, 
            unique=True)
    first_name = models.CharField(_('first name'), max_length=30, 
            blank=True)
    last_name = models.CharField(_('last name'), max_length=30, 
            blank=True)
    .....
Run Code Online (Sandbox Code Playgroud)

我的看法:

def search(request):
    result = publication.objects.all()
    query = request.GET.get("query")
    if query:
        result = result.filter(
            Q(title__icontains=query) |
            Q(user__first_name__icontains=query) |
            Q(user__email=query)
        ).distinct()
    user_filter = UserFilter(request.GET, queryset=result)

    return render(request, "search.html", {'filter': user_filter})
Run Code Online (Sandbox Code Playgroud)

我的过滤器:

class UserFilter(filters.FilterSet):
    title = filters.CharFilter(lookup_expr='icontains')
    first_name = filters.CharFilter(lookup_expr='iexact')
    user = filters.CharFilter(lookup_expr='exact')

    class Meta:
        model = publication
        fields = ['title', 'first_name', 'user']
Run Code Online (Sandbox Code Playgroud)

回溯(最近一次调用最后一次):

File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/views/generic/base.py", line 88, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django_filters/views.py", line 66, in get
    self.object_list = self.filterset.qs
  File "/usr/local/lib/python2.7/dist-packages/django_filters/filterset.py", line 214, in qs
    qs = filter_.filter(qs, value)
  File "/usr/local/lib/python2.7/dist-packages/django_filters/filters.py", line 171, in filter
    qs = self.get_method(qs)(**{'%s__%s' % (self.name, lookup): value})
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/db/models/query.py", line 781, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/db/models/query.py", line 799, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/db/models/sql/query.py", line 1260, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/db/models/sql/query.py", line 1286, in _add_q
    allow_joins=allow_joins, split_subq=split_subq,
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/db/models/sql/query.py", line 1216, in build_filter
    condition = lookup_class(lhs, value)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/db/models/lookups.py", line 24, in __init__
    self.rhs = self.get_prep_lookup()
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/db/models/fields/related_lookups.py", line 110, in get_prep_lookup
    self.rhs = target_field.get_prep_value(self.rhs)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11-py2.7.egg/django/db/models/fields/__init__.py", line 962, in get_prep_value
    return int(value)
ValueError: invalid literal for int() with base 10: 'abc@xyz.com'
Run Code Online (Sandbox Code Playgroud)

nev*_*ner 5

如果您需要按关系模型的字段进行过滤,您可以使用name归档类的参数:

class UserFilter(filters.FilterSet):
    title = filters.CharFilter(lookup_expr='icontains')
    first_name = filters.CharFilter(name='user__first_name', lookup_expr='iexact')
    user = filters.CharFilter(name='user__email', lookup_expr='exact')
Run Code Online (Sandbox Code Playgroud)

请参阅此处的详细信息。

UPD

要过滤全名,请尝试实现自定义方法:

full_name = CharFilter(method='my_custom_filter')
def my_custom_filter(self, queryset, name, value):
    first_name, last_name = value.split()
    return queryset.filter(Q(user__first_name__icontains=first_name) | Q(user__last_name__icontains=last_name))
Run Code Online (Sandbox Code Playgroud)