0001-misc-implement-customized-date-search-for-birthdate-.patch
src/authentic2/attribute_kinds.py | ||
---|---|---|
25 | 25 |
from django import forms |
26 | 26 |
from django.core.exceptions import ValidationError |
27 | 27 |
from django.core.validators import RegexValidator |
28 |
from django.utils import six |
|
28 |
from django.utils import six, formats
|
|
29 | 29 |
from django.utils.translation import ugettext_lazy as _, pgettext_lazy |
30 | 30 |
from django.utils import html |
31 | 31 |
from django.core.files.storage import default_storage |
32 |
from django.db.models import query |
|
32 | 33 | |
33 | 34 |
from django.utils.functional import keep_lazy |
34 | 35 | |
... | ... | |
207 | 208 |
return None |
208 | 209 | |
209 | 210 | |
211 |
def date_free_text_search(term): |
|
212 |
for date_format in formats.get_format('DATE_INPUT_FORMATS'): |
|
213 |
try: |
|
214 |
date = datetime.datetime.strptime(term, date_format).date() |
|
215 |
break |
|
216 |
except (ValueError, TypeError): |
|
217 |
pass |
|
218 |
else: |
|
219 |
return None |
|
220 |
return query.Q(attribute_values__content__exact=date.isoformat()) |
|
221 | ||
222 | ||
210 | 223 |
DEFAULT_ALLOW_BLANK = True |
211 | 224 |
DEFAULT_MAX_LENGTH = 256 |
212 | 225 | |
... | ... | |
251 | 264 |
'serialize': lambda x: x and x.isoformat(), |
252 | 265 |
'deserialize': lambda x: x and datetime.datetime.strptime(x, '%Y-%m-%d').date(), |
253 | 266 |
'rest_framework_field_class': BirthdateRestField, |
267 |
'free_text_search': date_free_text_search, |
|
254 | 268 |
}, |
255 | 269 |
{ |
256 | 270 |
'label': _('french postcode'), |
src/authentic2/custom_user/managers.py | ||
---|---|---|
37 | 37 |
searchable_attributes = Attribute.objects.filter(searchable=True) |
38 | 38 |
queries = [] |
39 | 39 |
for term in terms: |
40 |
q = None |
|
41 | ||
42 |
specific_queries = [] |
|
43 |
for a in searchable_attributes: |
|
44 |
kind = a.get_kind() |
|
45 |
free_text_search_function = kind.get('free_text_search') |
|
46 |
if free_text_search_function: |
|
47 |
q = free_text_search_function(term) |
|
48 |
if q is not None: |
|
49 |
specific_queries.append(q & models.query.Q(attribute_values__attribute=a)) |
|
50 | ||
51 |
# if the term is recognized by some specific attribute type, like a |
|
52 |
# date, does not use the later generic matcher |
|
53 |
if specific_queries is not None: |
|
54 |
queries.append(six.moves.reduce(models.query.Q.__or__, specific_queries)) |
|
55 |
continue |
|
56 | ||
40 | 57 |
q = ( |
41 | 58 |
models.query.Q(username__icontains=term) |
42 | 59 |
| models.query.Q(first_name__icontains=term) |
tests/test_api.py | ||
---|---|---|
1703 | 1703 |
assert len(resp.json['results']) == 2 |
1704 | 1704 |
resp = app.get('/api/users/', params={'modified__lt': '2019-10-27T02:58:07'}) |
1705 | 1705 |
assert len(resp.json['results']) == 0 |
1706 | ||
1707 | ||
1708 |
def test_free_text_search(app, admin, settings): |
|
1709 |
settings.LANGUAGE_CODE = 'fr' # use fr date format |
|
1710 | ||
1711 |
app.authorization = ('Basic', (admin.username, admin.username)) |
|
1712 |
Attribute.objects.create(kind='birthdate', name='birthdate', label='birthdate', required=False, searchable=True) |
|
1713 | ||
1714 |
user = User.objects.create() |
|
1715 |
user.attributes.birthdate = datetime.date(1982, 2, 10) |
|
1716 | ||
1717 |
resp = app.get('/api/users/?q=10/02/1982') |
|
1718 |
assert len(resp.json['results']) == 1 |
|
1719 |
assert resp.json['results'][0]['id'] == user.id |
|
1706 |
- |