misc: implement customized date search for birthdate attribute (#44656)
This commit is contained in:
parent
a67989da21
commit
e090ad25a7
|
@ -25,10 +25,11 @@ from itertools import chain
|
|||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import RegexValidator
|
||||
from django.utils import six
|
||||
from django.utils import six, formats
|
||||
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
|
||||
from django.utils import html
|
||||
from django.core.files.storage import default_storage
|
||||
from django.db.models import query
|
||||
|
||||
from django.utils.functional import keep_lazy
|
||||
|
||||
|
@ -207,6 +208,18 @@ def profile_attributes_ng_serialize(ctx, value):
|
|||
return None
|
||||
|
||||
|
||||
def date_free_text_search(term):
|
||||
for date_format in formats.get_format('DATE_INPUT_FORMATS'):
|
||||
try:
|
||||
date = datetime.datetime.strptime(term, date_format).date()
|
||||
break
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
else:
|
||||
return None
|
||||
return query.Q(attribute_values__content__exact=date.isoformat())
|
||||
|
||||
|
||||
DEFAULT_ALLOW_BLANK = True
|
||||
DEFAULT_MAX_LENGTH = 256
|
||||
|
||||
|
@ -251,6 +264,7 @@ DEFAULT_ATTRIBUTE_KINDS = [
|
|||
'serialize': lambda x: x and x.isoformat(),
|
||||
'deserialize': lambda x: x and datetime.datetime.strptime(x, '%Y-%m-%d').date(),
|
||||
'rest_framework_field_class': BirthdateRestField,
|
||||
'free_text_search': date_free_text_search,
|
||||
},
|
||||
{
|
||||
'label': _('french postcode'),
|
||||
|
|
|
@ -37,6 +37,23 @@ class UserQuerySet(models.QuerySet):
|
|||
searchable_attributes = Attribute.objects.filter(searchable=True)
|
||||
queries = []
|
||||
for term in terms:
|
||||
q = None
|
||||
|
||||
specific_queries = []
|
||||
for a in searchable_attributes:
|
||||
kind = a.get_kind()
|
||||
free_text_search_function = kind.get('free_text_search')
|
||||
if free_text_search_function:
|
||||
q = free_text_search_function(term)
|
||||
if q is not None:
|
||||
specific_queries.append(q & models.query.Q(attribute_values__attribute=a))
|
||||
|
||||
# if the term is recognized by some specific attribute type, like a
|
||||
# date, does not use the later generic matcher
|
||||
if specific_queries:
|
||||
queries.append(six.moves.reduce(models.query.Q.__or__, specific_queries))
|
||||
continue
|
||||
|
||||
q = (
|
||||
models.query.Q(username__icontains=term)
|
||||
| models.query.Q(first_name__icontains=term)
|
||||
|
|
|
@ -1703,3 +1703,17 @@ def test_filter_users_by_last_modification(app, admin, simple_user, freezer):
|
|||
assert len(resp.json['results']) == 2
|
||||
resp = app.get('/api/users/', params={'modified__lt': '2019-10-27T02:58:07'})
|
||||
assert len(resp.json['results']) == 0
|
||||
|
||||
|
||||
def test_free_text_search(app, admin, settings):
|
||||
settings.LANGUAGE_CODE = 'fr' # use fr date format
|
||||
|
||||
app.authorization = ('Basic', (admin.username, admin.username))
|
||||
Attribute.objects.create(kind='birthdate', name='birthdate', label='birthdate', required=False, searchable=True)
|
||||
|
||||
user = User.objects.create()
|
||||
user.attributes.birthdate = datetime.date(1982, 2, 10)
|
||||
|
||||
resp = app.get('/api/users/?q=10/02/1982')
|
||||
assert len(resp.json['results']) == 1
|
||||
assert resp.json['results'][0]['id'] == user.id
|
||||
|
|
Loading…
Reference in New Issue