recherche: première ébauche
[auf_framonde.git] / project / aldryn_search / utils.py
CommitLineData
5f23ec55
PH
1# -*- coding: utf-8 -*-
2from __future__ import unicode_literals
3
4import six
5
6from lxml.html.clean import Cleaner as LxmlCleaner
7
8from django.core.exceptions import ImproperlyConfigured
9from django.db import models
10try:
11 from django.utils.encoding import force_unicode
12except ImportError:
13 from django.utils.encoding import force_text as force_unicode
14from django.utils.importlib import import_module
15from django.utils.html import strip_tags as _strip_tags
16
17from haystack import DEFAULT_ALIAS
18from haystack.indexes import SearchIndex
19
20from cms.utils.i18n import get_language_code
21
22from .conf import settings
23
24
25def alias_from_language(language):
26 """
27 Returns alias if alias is a valid language.
28 """
29 language = get_language_code(language)
30
31 if language == settings.ALDRYN_SEARCH_DEFAULT_LANGUAGE:
32 return DEFAULT_ALIAS
33 return language
34
35
36def clean_join(separator, iterable):
37 """
38 Filters out iterable to only join non empty items.
39 """
40 return separator.join(filter(None, iterable))
41
42
43def get_callable(string_or_callable):
44 """
45 If given a callable then it returns it, otherwise it resolves the path
46 and returns an object.
47 """
48 if callable(string_or_callable):
49 return string_or_callable
50 else:
51 module_name, object_name = string_or_callable.rsplit('.', 1)
52 if module_name.startswith('aldryn_search'):
53 module_name = "project." + module_name
54 module = import_module(module_name)
55 return getattr(module, object_name)
56
57
58def _get_language_from_alias_func():
59 path_or_callable = settings.ALDRYN_SEARCH_LANGUAGE_FROM_ALIAS
60
61 if path_or_callable:
62 try:
63 func = get_callable(path_or_callable)
64 except AttributeError as error:
65 raise ImproperlyConfigured(
66 'ALDRYN_SEARCH_LANGUAGE_FROM_ALIAS: %s' % (str(error)))
67 if not callable(func):
68 raise ImproperlyConfigured(
69 'ALDRYN_SEARCH_LANGUAGE_FROM_ALIAS: %s is not callable' % func)
70 else:
71 func = None
72 return func
73
74
75def get_index_base():
76 index_string = settings.ALDRYN_SEARCH_INDEX_BASE_CLASS
77 try:
78 BaseClass = get_callable(index_string)
79 except AttributeError as error:
80 raise ImproperlyConfigured(
81 'ALDRYN_SEARCH_INDEX_BASE_CLASS: %s' % (str(error)))
82
83 if not issubclass(BaseClass, SearchIndex):
84 raise ImproperlyConfigured(
85 'ALDRYN_SEARCH_INDEX_BASE_CLASS: %s is not a subclass of haystack.indexes.SearchIndex' % index_string)
86
87 required_fields = ['text', 'language']
88
89 if not all(field in BaseClass.fields for field in required_fields):
90 raise ImproperlyConfigured('ALDRYN_SEARCH_INDEX_BASE_CLASS: %s must contain at least these fields: %s' % (
91 index_string, required_fields))
92 return BaseClass
93
94
95def language_from_alias(alias):
96 """
97 Returns alias if alias is a valid language.
98 """
99 languages = [language[0] for language in settings.LANGUAGES]
100
101 return alias if alias in languages else None
102
103
104def get_field_value(obj, name):
105 """
106 Given a model instance and a field name (or attribute),
107 returns the value of the field or an empty string.
108 """
109 fields = name.split('__')
110
111 name = fields[0]
112
113 try:
114 obj._meta.get_field(name)
115 except (AttributeError, models.FieldDoesNotExist):
116 # we catch attribute error because obj will not always be a model
117 # specially when going through multiple relationships.
118 value = getattr(obj, name, None) or ''
119 else:
120 value = getattr(obj, name)
121
122 if len(fields) > 1:
123 remaining = '__'.join(fields[1:])
124 return get_field_value(value, remaining)
125 return value
126
127
128def get_model_path(model_or_string):
129 if not isinstance(model_or_string, six.string_types):
130 # it's a model class
131 app_label = model_or_string._meta.app_label
132 model_name = model_or_string._meta.object_name
133 model_or_string = '{0}.{1}'.format(app_label, model_name)
134 return model_or_string.lower()
135
136
137def strip_tags(value):
138 """
139 Returns the given HTML with all tags stripped.
140 We use lxml to strip all js tags and then hand the result to django's strip tags.
141 """
142 # strip any new lines
143 value = value.strip()
144
145 if value:
146 partial_strip = LxmlCleaner().clean_html(value)
147 value = _strip_tags(partial_strip)
148 return value