django-searchkit 1.0__py3-none-any.whl → 1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- build/lib/build/lib/build/lib/example/example/__init__.py +0 -0
- build/lib/build/lib/build/lib/example/example/admin.py +16 -0
- build/lib/build/lib/build/lib/example/example/asgi.py +16 -0
- build/lib/build/lib/build/lib/example/example/management/__init__.py +0 -0
- build/lib/build/lib/build/lib/example/example/management/commands/__init__.py +0 -0
- build/lib/build/lib/build/lib/example/example/management/commands/createtestdata.py +62 -0
- build/lib/build/lib/build/lib/example/example/migrations/0001_initial.py +48 -0
- build/lib/build/lib/build/lib/example/example/migrations/__init__.py +0 -0
- build/lib/build/lib/build/lib/example/example/models.py +38 -0
- build/lib/build/lib/build/lib/example/example/settings.py +125 -0
- build/lib/build/lib/build/lib/example/example/urls.py +23 -0
- build/lib/build/lib/build/lib/example/example/wsgi.py +16 -0
- build/lib/build/lib/build/lib/searchkit/__init__.py +0 -0
- build/lib/build/lib/build/lib/searchkit/__version__.py +16 -0
- build/lib/build/lib/build/lib/searchkit/admin.py +30 -0
- build/lib/build/lib/build/lib/searchkit/apps.py +6 -0
- build/lib/build/lib/build/lib/searchkit/filters.py +28 -0
- build/lib/build/lib/build/lib/searchkit/forms/__init__.py +5 -0
- build/lib/build/lib/build/lib/searchkit/forms/fields.py +55 -0
- build/lib/build/lib/build/lib/searchkit/forms/search.py +62 -0
- build/lib/build/lib/build/lib/searchkit/forms/searchkit.py +154 -0
- build/lib/build/lib/build/lib/searchkit/forms/utils.py +178 -0
- build/lib/build/lib/build/lib/searchkit/migrations/0001_initial.py +30 -0
- build/lib/build/lib/build/lib/searchkit/migrations/0002_rename_searchkitsearch_search.py +18 -0
- build/lib/build/lib/build/lib/searchkit/migrations/__init__.py +0 -0
- build/lib/build/lib/build/lib/searchkit/models.py +21 -0
- build/lib/build/lib/build/lib/searchkit/templatetags/__init__.py +0 -0
- build/lib/build/lib/build/lib/searchkit/templatetags/searchkit.py +20 -0
- build/lib/build/lib/build/lib/searchkit/tests.py +400 -0
- build/lib/build/lib/build/lib/searchkit/urls.py +7 -0
- build/lib/build/lib/build/lib/searchkit/views.py +23 -0
- build/lib/build/lib/example/example/__init__.py +0 -0
- build/lib/build/lib/example/example/admin.py +16 -0
- build/lib/build/lib/example/example/asgi.py +16 -0
- build/lib/build/lib/example/example/management/__init__.py +0 -0
- build/lib/build/lib/example/example/management/commands/__init__.py +0 -0
- build/lib/build/lib/example/example/management/commands/createtestdata.py +62 -0
- build/lib/build/lib/example/example/migrations/0001_initial.py +48 -0
- build/lib/build/lib/example/example/migrations/__init__.py +0 -0
- build/lib/build/lib/example/example/models.py +38 -0
- build/lib/build/lib/example/example/settings.py +125 -0
- build/lib/build/lib/example/example/urls.py +23 -0
- build/lib/build/lib/example/example/wsgi.py +16 -0
- build/lib/build/lib/searchkit/__init__.py +0 -0
- build/lib/build/lib/searchkit/__version__.py +16 -0
- build/lib/build/lib/searchkit/admin.py +30 -0
- build/lib/build/lib/searchkit/apps.py +6 -0
- build/lib/build/lib/searchkit/filters.py +28 -0
- build/lib/build/lib/searchkit/forms/__init__.py +5 -0
- build/lib/build/lib/searchkit/forms/fields.py +55 -0
- build/lib/build/lib/searchkit/forms/search.py +62 -0
- build/lib/build/lib/searchkit/forms/searchkit.py +154 -0
- build/lib/build/lib/searchkit/forms/utils.py +178 -0
- build/lib/build/lib/searchkit/migrations/0001_initial.py +30 -0
- build/lib/build/lib/searchkit/migrations/0002_rename_searchkitsearch_search.py +18 -0
- build/lib/build/lib/searchkit/migrations/__init__.py +0 -0
- build/lib/build/lib/searchkit/models.py +21 -0
- build/lib/build/lib/searchkit/templatetags/__init__.py +0 -0
- build/lib/build/lib/searchkit/templatetags/searchkit.py +20 -0
- build/lib/build/lib/searchkit/tests.py +400 -0
- build/lib/build/lib/searchkit/urls.py +7 -0
- build/lib/build/lib/searchkit/views.py +23 -0
- build/lib/example/example/admin.py +1 -1
- build/lib/searchkit/__version__.py +1 -1
- build/lib/searchkit/admin.py +4 -4
- build/lib/searchkit/filters.py +10 -13
- build/lib/searchkit/forms/__init__.py +5 -3
- build/lib/searchkit/forms/search.py +37 -17
- build/lib/searchkit/forms/searchkit.py +60 -95
- build/lib/searchkit/forms/utils.py +44 -15
- build/lib/searchkit/migrations/0002_rename_searchkitsearch_search.py +18 -0
- build/lib/searchkit/models.py +2 -4
- build/lib/searchkit/templatetags/searchkit.py +0 -27
- build/lib/searchkit/tests.py +200 -50
- build/lib/searchkit/urls.py +1 -2
- build/lib/searchkit/views.py +11 -18
- {django_searchkit-1.0.dist-info → django_searchkit-1.2.dist-info}/METADATA +9 -24
- django_searchkit-1.2.dist-info/RECORD +130 -0
- example/example/admin.py +1 -1
- searchkit/__version__.py +1 -1
- searchkit/admin.py +4 -4
- searchkit/filters.py +10 -13
- searchkit/forms/__init__.py +5 -3
- searchkit/forms/search.py +37 -17
- searchkit/forms/searchkit.py +60 -95
- searchkit/forms/utils.py +44 -15
- searchkit/migrations/0002_rename_searchkitsearch_search.py +18 -0
- searchkit/models.py +2 -4
- searchkit/templatetags/searchkit.py +0 -27
- searchkit/tests.py +200 -50
- searchkit/urls.py +1 -2
- searchkit/views.py +11 -18
- django_searchkit-1.0.dist-info/RECORD +0 -66
- {django_searchkit-1.0.dist-info → django_searchkit-1.2.dist-info}/WHEEL +0 -0
- {django_searchkit-1.0.dist-info → django_searchkit-1.2.dist-info}/licenses/LICENCE +0 -0
- {django_searchkit-1.0.dist-info → django_searchkit-1.2.dist-info}/top_level.txt +0 -0
- {django_searchkit-1.0.dist-info → django_searchkit-1.2.dist-info}/zip-safe +0 -0
build/lib/searchkit/tests.py
CHANGED
@@ -1,19 +1,29 @@
|
|
1
|
+
from urllib.parse import urlencode
|
1
2
|
from django.test import TestCase
|
2
3
|
from django.contrib.contenttypes.models import ContentType
|
3
|
-
from django import
|
4
|
+
from django.contrib.auth.models import User
|
5
|
+
from django.urls import reverse
|
4
6
|
from example.models import ModelA
|
7
|
+
from example.management.commands.createtestdata import Command as CreateTestData
|
5
8
|
from searchkit.forms.utils import FIELD_PLAN
|
6
9
|
from searchkit.forms.utils import SUPPORTED_FIELDS
|
7
|
-
from searchkit.forms.utils import
|
8
|
-
from searchkit.forms import
|
9
|
-
from searchkit.forms import
|
10
|
-
from searchkit.forms import
|
10
|
+
from searchkit.forms.utils import ModelTree
|
11
|
+
from searchkit.forms import SearchForm
|
12
|
+
from searchkit.forms import SearchkitModelForm
|
13
|
+
from searchkit.forms import BaseSearchkitFormSet
|
14
|
+
from searchkit.forms import searchkit_formset_factory
|
15
|
+
from searchkit.models import Search
|
16
|
+
from searchkit import __version__
|
17
|
+
|
18
|
+
|
19
|
+
SearchkitFormSet = searchkit_formset_factory(model=ModelA)
|
20
|
+
SearchkitForm = SearchkitFormSet.form
|
11
21
|
|
12
22
|
|
13
23
|
INITIAL_DATA = [
|
14
24
|
dict(
|
15
25
|
field='model_b__chars',
|
16
|
-
operator='
|
26
|
+
operator='contains',
|
17
27
|
value='anytext',
|
18
28
|
),
|
19
29
|
dict(
|
@@ -23,12 +33,12 @@ INITIAL_DATA = [
|
|
23
33
|
),
|
24
34
|
dict(
|
25
35
|
field='float',
|
26
|
-
operator='
|
36
|
+
operator='gt',
|
27
37
|
value='0.3',
|
28
38
|
),
|
29
39
|
dict(
|
30
40
|
field='decimal',
|
31
|
-
operator='
|
41
|
+
operator='lte',
|
32
42
|
value='1.23',
|
33
43
|
),
|
34
44
|
dict(
|
@@ -43,20 +53,29 @@ INITIAL_DATA = [
|
|
43
53
|
)
|
44
54
|
]
|
45
55
|
|
46
|
-
add_prefix = lambda i: SearchkitFormSet(
|
56
|
+
add_prefix = lambda i: SearchkitFormSet().add_prefix(i)
|
57
|
+
contenttype = ContentType.objects.get_for_model(ModelA)
|
47
58
|
DEFAULT_PREFIX = SearchkitFormSet.get_default_prefix()
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
}
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
59
|
+
|
60
|
+
def get_form_data(initial_data=INITIAL_DATA):
|
61
|
+
count = len(initial_data)
|
62
|
+
data = {
|
63
|
+
'name': 'test search', # The name of the search.
|
64
|
+
'searchkit_model': f'{contenttype.pk}', # Data for the searchkit-model form.
|
65
|
+
f'{DEFAULT_PREFIX}-TOTAL_FORMS': f'{count}', # Data for the managment form.
|
66
|
+
f'{DEFAULT_PREFIX}-INITIAL_FORMS': f'{count}', # Data for the managment form.
|
67
|
+
}
|
68
|
+
for i, d in enumerate(initial_data):
|
69
|
+
prefix = SearchkitFormSet().add_prefix(i)
|
70
|
+
for key, value in d.items():
|
71
|
+
if isinstance(value, list):
|
72
|
+
for i, v in enumerate(value):
|
73
|
+
data.update({f'{prefix}-{key}_{i}': v})
|
74
|
+
else:
|
75
|
+
data.update({f'{prefix}-{key}': value})
|
76
|
+
return data
|
77
|
+
|
78
|
+
FORM_DATA = get_form_data()
|
60
79
|
|
61
80
|
|
62
81
|
class CheckFormMixin:
|
@@ -70,22 +89,19 @@ class CheckFormMixin:
|
|
70
89
|
self.assertIn('value', form.fields)
|
71
90
|
self.assertEqual(len(form.fields), 3)
|
72
91
|
|
73
|
-
# Check choices
|
92
|
+
# Check field choices for the model.
|
74
93
|
form_model_field = form.fields['field']
|
75
94
|
self.assertTrue(form_model_field.choices)
|
76
95
|
options = [c[0] for c in form_model_field.choices]
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
if isinstance(model_field, tuple(SUPPORTED_FIELDS)):
|
87
|
-
lookup_path = f'{model_field.name}__{remote_field.name}'
|
88
|
-
self.assertIn(lookup_path, options)
|
96
|
+
tree = ModelTree(ModelA)
|
97
|
+
for node in tree.iterate():
|
98
|
+
for model_field in node.model._meta.fields:
|
99
|
+
if not any(isinstance(model_field, f) for f in SUPPORTED_FIELDS):
|
100
|
+
continue
|
101
|
+
if node.is_root:
|
102
|
+
self.assertIn(model_field.name, options)
|
103
|
+
else:
|
104
|
+
self.assertIn(f'{node.field_path}__{model_field.name}', options)
|
89
105
|
|
90
106
|
# Check the field_plan choosen based on the model_field.
|
91
107
|
field_plan = next(iter([p for t, p in FIELD_PLAN.items() if t(form.model_field)]))
|
@@ -102,7 +118,7 @@ class CheckFormMixin:
|
|
102
118
|
class SearchkitFormTestCase(CheckFormMixin, TestCase):
|
103
119
|
|
104
120
|
def test_blank_searchkitform(self):
|
105
|
-
form = SearchkitForm(
|
121
|
+
form = SearchkitForm(prefix=add_prefix(0))
|
106
122
|
self.check_form(form)
|
107
123
|
|
108
124
|
# Form should not be bound or valid.
|
@@ -113,7 +129,7 @@ class SearchkitFormTestCase(CheckFormMixin, TestCase):
|
|
113
129
|
data = {
|
114
130
|
f'{add_prefix(0)}-field': 'foobar',
|
115
131
|
}
|
116
|
-
form = SearchkitForm(
|
132
|
+
form = SearchkitForm(data, prefix=add_prefix(0))
|
117
133
|
self.check_form(form)
|
118
134
|
|
119
135
|
# Form should be invalid.
|
@@ -127,7 +143,7 @@ class SearchkitFormTestCase(CheckFormMixin, TestCase):
|
|
127
143
|
data = {
|
128
144
|
f'{add_prefix(0)}-field': 'integer',
|
129
145
|
}
|
130
|
-
form = SearchkitForm(
|
146
|
+
form = SearchkitForm(data, prefix=add_prefix(0))
|
131
147
|
self.check_form(form)
|
132
148
|
|
133
149
|
# Form should be invalid since no value data is provieded.
|
@@ -138,7 +154,7 @@ class SearchkitFormTestCase(CheckFormMixin, TestCase):
|
|
138
154
|
f'{add_prefix(0)}-field': 'integer',
|
139
155
|
f'{add_prefix(0)}-operator': 'foobar',
|
140
156
|
}
|
141
|
-
form = SearchkitForm(
|
157
|
+
form = SearchkitForm(data, prefix=add_prefix(0))
|
142
158
|
self.check_form(form)
|
143
159
|
|
144
160
|
# Form should be invalid.
|
@@ -153,7 +169,7 @@ class SearchkitFormTestCase(CheckFormMixin, TestCase):
|
|
153
169
|
f'{add_prefix(0)}-field': 'integer',
|
154
170
|
f'{add_prefix(0)}-operator': 'exact',
|
155
171
|
}
|
156
|
-
form = SearchkitForm(
|
172
|
+
form = SearchkitForm(data, prefix=add_prefix(0))
|
157
173
|
self.check_form(form)
|
158
174
|
|
159
175
|
# Form should be invalid since no value data is provieded.
|
@@ -165,7 +181,7 @@ class SearchkitFormTestCase(CheckFormMixin, TestCase):
|
|
165
181
|
f'{add_prefix(0)}-operator': 'exact',
|
166
182
|
f'{add_prefix(0)}-value': '123',
|
167
183
|
}
|
168
|
-
form = SearchkitForm(
|
184
|
+
form = SearchkitForm(data, prefix=add_prefix(0))
|
169
185
|
self.check_form(form)
|
170
186
|
|
171
187
|
# Form should be valid.
|
@@ -177,7 +193,7 @@ class SearchkitFormTestCase(CheckFormMixin, TestCase):
|
|
177
193
|
f'{add_prefix(0)}-operator': 'exact',
|
178
194
|
f'{add_prefix(0)}-value': 'foobar',
|
179
195
|
}
|
180
|
-
form = SearchkitForm(
|
196
|
+
form = SearchkitForm(data, prefix=add_prefix(0))
|
181
197
|
self.check_form(form)
|
182
198
|
|
183
199
|
# Form should be invalid.
|
@@ -204,7 +220,7 @@ class SearchkitFormSetTestCase(CheckFormMixin, TestCase):
|
|
204
220
|
def test_searchkit_formset_with_invalid_data(self):
|
205
221
|
data = FORM_DATA.copy()
|
206
222
|
del data[f'{add_prefix(0)}-value']
|
207
|
-
formset = SearchkitFormSet(data
|
223
|
+
formset = SearchkitFormSet(data)
|
208
224
|
self.assertFalse(formset.is_valid())
|
209
225
|
|
210
226
|
# Check error message in html.
|
@@ -212,7 +228,8 @@ class SearchkitFormSetTestCase(CheckFormMixin, TestCase):
|
|
212
228
|
self.assertIn(errors, formset.forms[0].errors.values())
|
213
229
|
|
214
230
|
def test_searchkit_formset_with_initial_data(self):
|
215
|
-
|
231
|
+
formset_class = searchkit_formset_factory(model=ModelA, extra=0)
|
232
|
+
formset = formset_class(initial=INITIAL_DATA)
|
216
233
|
self.assertFalse(formset.is_bound)
|
217
234
|
self.assertFalse(formset.is_valid())
|
218
235
|
self.assertEqual(len(formset.forms), len(INITIAL_DATA))
|
@@ -223,17 +240,17 @@ class SearchkitFormSetTestCase(CheckFormMixin, TestCase):
|
|
223
240
|
|
224
241
|
class SearchkitSearchFormTestCase(TestCase):
|
225
242
|
def test_searchkit_search_form_without_data(self):
|
226
|
-
form =
|
243
|
+
form = SearchForm()
|
227
244
|
self.assertFalse(form.is_bound)
|
228
245
|
self.assertFalse(form.is_valid())
|
229
|
-
self.assertIsInstance(form.formset,
|
246
|
+
self.assertIsInstance(form.formset, BaseSearchkitFormSet)
|
230
247
|
self.assertEqual(form.formset.model, None)
|
231
248
|
|
232
249
|
def test_searchkit_search_form_with_data(self):
|
233
|
-
form =
|
250
|
+
form = SearchForm(FORM_DATA)
|
234
251
|
self.assertTrue(form.is_bound)
|
235
252
|
self.assertTrue(form.is_valid())
|
236
|
-
self.assertIsInstance(form.formset,
|
253
|
+
self.assertIsInstance(form.formset, BaseSearchkitFormSet)
|
237
254
|
self.assertEqual(form.formset.model, ModelA)
|
238
255
|
self.assertEqual(form.instance.data, form.formset.cleaned_data)
|
239
256
|
|
@@ -242,9 +259,142 @@ class SearchkitSearchFormTestCase(TestCase):
|
|
242
259
|
self.assertTrue(form.instance.pk)
|
243
260
|
|
244
261
|
# Using the instance data as filter rules works.
|
245
|
-
filter_rules = form.instance.
|
262
|
+
filter_rules = form.instance.as_lookups()
|
246
263
|
self.assertEqual(len(filter_rules), len(INITIAL_DATA))
|
247
264
|
for data in INITIAL_DATA:
|
248
265
|
self.assertIn(f"{data['field']}__{data['operator']}", filter_rules)
|
249
|
-
|
250
|
-
|
266
|
+
|
267
|
+
|
268
|
+
class SearchkitModelFormTestCase(TestCase):
|
269
|
+
def test_searchkit_model_form_choices(self):
|
270
|
+
form = SearchkitModelForm()
|
271
|
+
labels = [c[1] for c in form.fields['searchkit_model'].choices]
|
272
|
+
self.assertEqual(len(labels), 3)
|
273
|
+
self.assertEqual('select a model', labels[0].lower())
|
274
|
+
self.assertEqual('example | model a', labels[1].lower())
|
275
|
+
self.assertEqual('example | model b', labels[2].lower())
|
276
|
+
|
277
|
+
|
278
|
+
class AdminBackendTest(TestCase):
|
279
|
+
@classmethod
|
280
|
+
def setUpTestData(cls):
|
281
|
+
CreateTestData().handle()
|
282
|
+
|
283
|
+
def setUp(self):
|
284
|
+
admin = User.objects.get(username='admin')
|
285
|
+
self.client.force_login(admin)
|
286
|
+
|
287
|
+
def test_search_form(self):
|
288
|
+
url = reverse('admin:searchkit_search_add')
|
289
|
+
resp = self.client.get(url)
|
290
|
+
self.assertEqual(resp.status_code, 200)
|
291
|
+
select = b'<select name="searchkit_model" class="searchkit-reload-on-change" data-total-forms="1" required id="id_searchkit_model">'
|
292
|
+
for snippet in select.split(b' '):
|
293
|
+
self.assertIn(snippet, resp.content)
|
294
|
+
|
295
|
+
def test_search_form_with_initial(self):
|
296
|
+
url = reverse('admin:searchkit_search_add') + '?searchkit_model=1'
|
297
|
+
resp = self.client.get(url)
|
298
|
+
self.assertEqual(resp.status_code, 200)
|
299
|
+
select = '<select name="searchkit_model" class="searchkit-reload-on-change" data-total-forms="1" required id="id_searchkit_model">'
|
300
|
+
for snippet in select.split(' '):
|
301
|
+
self.assertIn(snippet, str(resp.content))
|
302
|
+
self.assertIn('<option value="1" selected>', str(resp.content))
|
303
|
+
self.assertIn('name="searchkit-example-modela-0-field"', str(resp.content))
|
304
|
+
|
305
|
+
def test_add_search(self):
|
306
|
+
# Create a search object via the admin backend.
|
307
|
+
url = reverse('admin:searchkit_search_add')
|
308
|
+
data = FORM_DATA.copy()
|
309
|
+
data['_save_and_apply'] = True
|
310
|
+
resp = self.client.post(url, data, follow=True)
|
311
|
+
self.assertEqual(resp.status_code, 200)
|
312
|
+
self.assertEqual(len(Search.objects.all()), 1)
|
313
|
+
|
314
|
+
# Change it via backend.
|
315
|
+
url = reverse('admin:searchkit_search_change', args=(1,))
|
316
|
+
data['name'] = 'Changed name'
|
317
|
+
data['searchkit-example-modela-0-field'] = 'boolean'
|
318
|
+
data['searchkit-example-modela-0-operator'] = 'exact'
|
319
|
+
data['searchkit-example-modela-0-value'] = 'true'
|
320
|
+
resp = self.client.post(url, data, follow=True)
|
321
|
+
self.assertEqual(resp.status_code, 200)
|
322
|
+
self.assertEqual(Search.objects.get(pk=1).name, data['name'])
|
323
|
+
|
324
|
+
# Will the search be listed in the admin filter?
|
325
|
+
url = reverse('admin:example_modela_changelist')
|
326
|
+
resp = self.client.get(url)
|
327
|
+
self.assertEqual(resp.status_code, 200)
|
328
|
+
self.assertIn('href="?search=1"', str(resp.content))
|
329
|
+
self.assertIn(data['name'], str(resp.content))
|
330
|
+
|
331
|
+
|
332
|
+
class SearchViewTest(TestCase):
|
333
|
+
|
334
|
+
def setUp(self):
|
335
|
+
self.initial = [
|
336
|
+
dict(
|
337
|
+
field='integer',
|
338
|
+
operator='exact',
|
339
|
+
value=1,
|
340
|
+
)
|
341
|
+
]
|
342
|
+
self.initial_range = [
|
343
|
+
dict(
|
344
|
+
field='integer',
|
345
|
+
operator='range',
|
346
|
+
value=[1,3],
|
347
|
+
)
|
348
|
+
]
|
349
|
+
|
350
|
+
def test_search_view_invalid_data(self):
|
351
|
+
initial = self.initial.copy()
|
352
|
+
initial[0]['value'] = 'no integer'
|
353
|
+
data = get_form_data(initial)
|
354
|
+
url_params = urlencode(data)
|
355
|
+
base_url = reverse('searchkit_form')
|
356
|
+
url = f'{base_url}?{url_params}'
|
357
|
+
resp = self.client.get(url)
|
358
|
+
self.assertEqual(resp.status_code, 200)
|
359
|
+
html_error = '<li>Enter a whole number.</li>'
|
360
|
+
self.assertInHTML(html_error, str(resp.content))
|
361
|
+
|
362
|
+
def test_search_view_missing_data(self):
|
363
|
+
initial = self.initial.copy()
|
364
|
+
del(initial[0]['value'])
|
365
|
+
data = get_form_data(initial)
|
366
|
+
url_params = urlencode(data)
|
367
|
+
base_url = reverse('searchkit_form')
|
368
|
+
url = f'{base_url}?{url_params}'
|
369
|
+
resp = self.client.get(url)
|
370
|
+
self.assertEqual(resp.status_code, 200)
|
371
|
+
html_error = '<li>This field is required.</li>'
|
372
|
+
self.assertInHTML(html_error, str(resp.content))
|
373
|
+
|
374
|
+
def test_search_view_with_range_operator(self):
|
375
|
+
data = get_form_data(self.initial_range)
|
376
|
+
url_params = urlencode(data)
|
377
|
+
base_url = reverse('searchkit_form')
|
378
|
+
url = f'{base_url}?{url_params}'
|
379
|
+
resp = self.client.get(url)
|
380
|
+
self.assertEqual(resp.status_code, 200)
|
381
|
+
html = '<input type="number" name="searchkit-example-modela-0-value_1" value="3" id="id_searchkit-example-modela-0-value_1">'
|
382
|
+
self.assertInHTML(html, str(resp.content))
|
383
|
+
|
384
|
+
def test_search_view_with_model(self):
|
385
|
+
data = get_form_data(self.initial)
|
386
|
+
data['searchkit_model'] = ContentType.objects.get_for_model(ModelA).pk
|
387
|
+
url_params = urlencode(data)
|
388
|
+
base_url = reverse('searchkit_form')
|
389
|
+
url = f'{base_url}?{url_params}'
|
390
|
+
resp = self.client.get(url)
|
391
|
+
self.assertEqual(resp.status_code, 200)
|
392
|
+
|
393
|
+
def test_search_view_with_invalid_model(self):
|
394
|
+
data = get_form_data(self.initial)
|
395
|
+
data['searchkit_model'] = 9999 # Non-existing content type.
|
396
|
+
url_params = urlencode(data)
|
397
|
+
base_url = reverse('searchkit_form')
|
398
|
+
url = f'{base_url}?{url_params}'
|
399
|
+
resp = self.client.get(url)
|
400
|
+
self.assertEqual(resp.status_code, 400)
|
build/lib/searchkit/urls.py
CHANGED
@@ -3,6 +3,5 @@ from .views import SearchkitAjaxView
|
|
3
3
|
|
4
4
|
|
5
5
|
urlpatterns = [
|
6
|
-
path("searchkit/
|
7
|
-
path("searchkit/form/<slug:app_label>/<slug:model_name>/", SearchkitAjaxView.as_view(), name="searchkit_form_model"),
|
6
|
+
path("searchkit/", SearchkitAjaxView.as_view(), name="searchkit_form"),
|
8
7
|
]
|
build/lib/searchkit/views.py
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
from django.utils.translation import gettext_lazy as _
|
2
2
|
from django.http import HttpResponse
|
3
|
-
from django.http import Http404
|
3
|
+
from django.http import Http404, HttpResponseBadRequest
|
4
4
|
from django.apps import apps
|
5
|
+
from django.contrib.contenttypes.models import ContentType
|
5
6
|
from django.views.generic import View
|
6
|
-
from .forms import
|
7
|
+
from .forms import SearchkitModelForm
|
8
|
+
from .forms import searchkit_formset_factory
|
7
9
|
|
8
10
|
|
9
11
|
# FIXME: Check permissions and authentication.
|
@@ -11,20 +13,11 @@ class SearchkitAjaxView(View):
|
|
11
13
|
"""
|
12
14
|
Reload the formset via ajax.
|
13
15
|
"""
|
14
|
-
def get_model(self, **kwargs):
|
15
|
-
"""
|
16
|
-
Get the model from the URL parameters.
|
17
|
-
"""
|
18
|
-
if all(k in kwargs for k in ('app_label', 'model_name')):
|
19
|
-
app_label, model_name = kwargs['app_label'], kwargs['model_name']
|
20
|
-
try:
|
21
|
-
return apps.get_model(app_label=app_label, model_name=model_name)
|
22
|
-
except LookupError:
|
23
|
-
raise Http404(_('Model %s.%s not found') % (app_label, model_name))
|
24
|
-
else:
|
25
|
-
return None
|
26
|
-
|
27
16
|
def get(self, request, **kwargs):
|
28
|
-
|
29
|
-
|
30
|
-
|
17
|
+
model_form = SearchkitModelForm(data=self.request.GET)
|
18
|
+
if model_form.is_valid():
|
19
|
+
model = model_form.cleaned_data['searchkit_model'].model_class()
|
20
|
+
formset = searchkit_formset_factory(model=model)(data=request.GET)
|
21
|
+
return HttpResponse(formset.render())
|
22
|
+
else:
|
23
|
+
return HttpResponseBadRequest(_('Invalid searchkit-model-form.'))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: django-searchkit
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.2
|
4
4
|
Summary: Finally a real searchkit for django!
|
5
5
|
Home-page: https://github.com/thomst/django-searchkit
|
6
6
|
Author: Thomas Leichtfuß
|
@@ -9,8 +9,6 @@ License: BSD License
|
|
9
9
|
Platform: OS Independent
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
11
11
|
Classifier: Framework :: Django
|
12
|
-
Classifier: Framework :: Django :: 3.1
|
13
|
-
Classifier: Framework :: Django :: 3.2
|
14
12
|
Classifier: Framework :: Django :: 4.0
|
15
13
|
Classifier: Framework :: Django :: 4.1
|
16
14
|
Classifier: Framework :: Django :: 4.2
|
@@ -22,8 +20,6 @@ Classifier: License :: OSI Approved :: BSD License
|
|
22
20
|
Classifier: Operating System :: OS Independent
|
23
21
|
Classifier: Programming Language :: Python
|
24
22
|
Classifier: Programming Language :: Python :: 3
|
25
|
-
Classifier: Programming Language :: Python :: 3.7
|
26
|
-
Classifier: Programming Language :: Python :: 3.8
|
27
23
|
Classifier: Programming Language :: Python :: 3.9
|
28
24
|
Classifier: Programming Language :: Python :: 3.10
|
29
25
|
Classifier: Programming Language :: Python :: 3.11
|
@@ -32,8 +28,9 @@ Classifier: Topic :: Software Development
|
|
32
28
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
33
29
|
Description-Content-Type: text/markdown
|
34
30
|
License-File: LICENCE
|
35
|
-
Requires-Dist: Django>=
|
31
|
+
Requires-Dist: Django>=4.0
|
36
32
|
Requires-Dist: django-picklefield>=2.0
|
33
|
+
Requires-Dist: django-modeltree
|
37
34
|
Dynamic: author
|
38
35
|
Dynamic: author-email
|
39
36
|
Dynamic: classifier
|
@@ -50,8 +47,8 @@ Dynamic: summary
|
|
50
47
|
|
51
48
|
[<img src="https://github.com/thomst/django-searchkit/actions/workflows/ci.yml/badge.svg">](https://github.com/thomst/django-searchkit/)
|
52
49
|
[<img src="https://coveralls.io/repos/github/thomst/django-searchkit/badge.svg?branch=main">](https://coveralls.io/github/thomst/django-searchkit?branch=main)
|
53
|
-
[<img src="https://img.shields.io/badge/python-3.
|
54
|
-
[<img src="https://img.shields.io/badge/django-
|
50
|
+
[<img src="https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11-blue">](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11-blue)
|
51
|
+
[<img src="https://img.shields.io/badge/django-4.0%20%7C%204.1%20%7C%204.2%20%7C%205.0%20%7C%205.1%20%7C%205.2-orange">](https://img.shields.io/badge/django-4.0%20%7C%204.1%20%7C%204.2%20%7C%205.0%20%7C%205.1%20%7C%205.2-orange)
|
55
52
|
|
56
53
|
|
57
54
|
## Description
|
@@ -99,20 +96,8 @@ class MyModelAdmin(admin.ModelAdmin):
|
|
99
96
|
## Usage
|
100
97
|
|
101
98
|
1. Open the admin changelist of your Model.
|
102
|
-
2. Click "Add filter"
|
103
|
-
3.
|
99
|
+
2. Click the "Add filter" button of the Searchkit filter.
|
100
|
+
3. Give your Filter a name.
|
104
101
|
4. Configure as many filter rules as you want.
|
105
|
-
5. Click "Save and apply"
|
106
|
-
|
107
|
-
|
108
|
-
## TODO
|
109
|
-
|
110
|
-
- Limit the choices of the model field by models that should be searchable.
|
111
|
-
- Add an apply button to the search edit page to be able to use a search without
|
112
|
-
saving it.
|
113
|
-
- Coming from the search edit page the filtering should be done by an id__in url
|
114
|
-
parameter, not by an search parameter as it is used by the searchkit filter.
|
115
|
-
- Preselect the right model in the model field when coming from a models
|
116
|
-
changelist by the "Add filter" button.
|
117
|
-
- Add a public field for searches and only offer public searches in the
|
118
|
-
searchkit filter.
|
102
|
+
5. Click "Save and apply".
|
103
|
+
6. Reuse your filter whenever you want using the Searchkit filter section.
|
@@ -0,0 +1,130 @@
|
|
1
|
+
build/lib/build/lib/build/lib/example/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
build/lib/build/lib/build/lib/example/example/admin.py,sha256=eTZ5mCA1ToGouqYgIf-6xDl2nvYAz7T9lU1Bnu_gP9c,462
|
3
|
+
build/lib/build/lib/build/lib/example/example/asgi.py,sha256=mqLnzcCH9X-8UhDo5ZhcM8tF3jtALEGSjsBmphbkLcs,391
|
4
|
+
build/lib/build/lib/build/lib/example/example/models.py,sha256=fB9X782cX01Yg2uIiPCVgrS8C7DkgG9U-9mxGtX3P7Q,1097
|
5
|
+
build/lib/build/lib/build/lib/example/example/settings.py,sha256=du9bWbAceSvDkYeNYOc_3KxKL1p1se93TdAueT2RQ_E,3256
|
6
|
+
build/lib/build/lib/build/lib/example/example/urls.py,sha256=D8LxjiTdJSA87AVh3BzpVo5E2aC30hlp20HshPDrfvU,800
|
7
|
+
build/lib/build/lib/build/lib/example/example/wsgi.py,sha256=OAXHHeNQoj7FBDc5NMET39i_kIGpFrcdNDdY1thrh58,391
|
8
|
+
build/lib/build/lib/build/lib/example/example/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
build/lib/build/lib/build/lib/example/example/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
+
build/lib/build/lib/build/lib/example/example/management/commands/createtestdata.py,sha256=IVtyUqak133h9Ua-Ag_GP8mw3dUdiDYAa2tGmLkKluU,2737
|
11
|
+
build/lib/build/lib/build/lib/example/example/migrations/0001_initial.py,sha256=62tOi17oHGuqqLmSAYWLep6AMkxCJF6Tp13odghS7gI,2014
|
12
|
+
build/lib/build/lib/build/lib/example/example/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
+
build/lib/build/lib/build/lib/searchkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
+
build/lib/build/lib/build/lib/searchkit/__version__.py,sha256=g6zhPyD9UelvcYrhtmQjIk-7_RH9Bu2W8YLlyW3M5OM,661
|
15
|
+
build/lib/build/lib/build/lib/searchkit/admin.py,sha256=URZgMKnfKlDqOgmQXJHu7mFGrjwkElpunAUbp2_9JcA,1182
|
16
|
+
build/lib/build/lib/build/lib/searchkit/apps.py,sha256=17m6wPu5N59Dq4MLoWaQd0aNHEzMT4z4emQD632GIMA,150
|
17
|
+
build/lib/build/lib/build/lib/searchkit/filters.py,sha256=l8756ftyURUpK3KSkl__TDP5KpqaapxjYMaAjh729ps,1098
|
18
|
+
build/lib/build/lib/build/lib/searchkit/models.py,sha256=0LEe0z3jOTqAGrqNGknDDY1L1anaG3kCcQ_Zm_7dl9I,800
|
19
|
+
build/lib/build/lib/build/lib/searchkit/tests.py,sha256=qm8rvKC8aDnaspIXwzCsDwMkfXMR4uOHzqDLWhdv2dA,14849
|
20
|
+
build/lib/build/lib/build/lib/searchkit/urls.py,sha256=Mhrq4CUOhrh28ZhRocSP2AYnfWFW2c_eJyMR81q5fps,162
|
21
|
+
build/lib/build/lib/build/lib/searchkit/views.py,sha256=ECSwsge2pD0OJLHdHwpOdWS7XiItUX2NFCO8FSjBigE,919
|
22
|
+
build/lib/build/lib/build/lib/searchkit/forms/__init__.py,sha256=FBggDa1owkYrceIU3cqNhqsMB49RJWZRAkA4OfvUMcM,207
|
23
|
+
build/lib/build/lib/build/lib/searchkit/forms/fields.py,sha256=TpFZdAyWKaMhOoZFTuy5ODNrW6RLy289Lk1fcMSGJ20,1621
|
24
|
+
build/lib/build/lib/build/lib/searchkit/forms/search.py,sha256=mca67piLDqKUhXzaKIOztk5Gg8V1XL21n27aIffH88A,2330
|
25
|
+
build/lib/build/lib/build/lib/searchkit/forms/searchkit.py,sha256=pg3vw6dMdtaHja-g1Yh72XJkLp7I48nXht9zxWbGW9Y,6022
|
26
|
+
build/lib/build/lib/build/lib/searchkit/forms/utils.py,sha256=m8vwB-3AoYuMx0QxlJTwSWbDHBG8MyCxFmsyK6xyai8,5221
|
27
|
+
build/lib/build/lib/build/lib/searchkit/migrations/0001_initial.py,sha256=cP886X1UMrDTf-KxfHfuoQ4b1T1lhdNJyVNOGMNyWNw,1093
|
28
|
+
build/lib/build/lib/build/lib/searchkit/migrations/0002_rename_searchkitsearch_search.py,sha256=RHXShizf689AdPb2Ca-hONWmwZbB2Fs5DQhXlEPE-f0,389
|
29
|
+
build/lib/build/lib/build/lib/searchkit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
|
+
build/lib/build/lib/build/lib/searchkit/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
|
+
build/lib/build/lib/build/lib/searchkit/templatetags/searchkit.py,sha256=HpEGTGYi_enDh_bgTgWdVbZftNuZqRt4J9N5A0Nc1AM,581
|
32
|
+
build/lib/build/lib/example/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
|
+
build/lib/build/lib/example/example/admin.py,sha256=eTZ5mCA1ToGouqYgIf-6xDl2nvYAz7T9lU1Bnu_gP9c,462
|
34
|
+
build/lib/build/lib/example/example/asgi.py,sha256=mqLnzcCH9X-8UhDo5ZhcM8tF3jtALEGSjsBmphbkLcs,391
|
35
|
+
build/lib/build/lib/example/example/models.py,sha256=fB9X782cX01Yg2uIiPCVgrS8C7DkgG9U-9mxGtX3P7Q,1097
|
36
|
+
build/lib/build/lib/example/example/settings.py,sha256=du9bWbAceSvDkYeNYOc_3KxKL1p1se93TdAueT2RQ_E,3256
|
37
|
+
build/lib/build/lib/example/example/urls.py,sha256=D8LxjiTdJSA87AVh3BzpVo5E2aC30hlp20HshPDrfvU,800
|
38
|
+
build/lib/build/lib/example/example/wsgi.py,sha256=OAXHHeNQoj7FBDc5NMET39i_kIGpFrcdNDdY1thrh58,391
|
39
|
+
build/lib/build/lib/example/example/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
40
|
+
build/lib/build/lib/example/example/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
41
|
+
build/lib/build/lib/example/example/management/commands/createtestdata.py,sha256=IVtyUqak133h9Ua-Ag_GP8mw3dUdiDYAa2tGmLkKluU,2737
|
42
|
+
build/lib/build/lib/example/example/migrations/0001_initial.py,sha256=62tOi17oHGuqqLmSAYWLep6AMkxCJF6Tp13odghS7gI,2014
|
43
|
+
build/lib/build/lib/example/example/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
|
+
build/lib/build/lib/searchkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
45
|
+
build/lib/build/lib/searchkit/__version__.py,sha256=g6zhPyD9UelvcYrhtmQjIk-7_RH9Bu2W8YLlyW3M5OM,661
|
46
|
+
build/lib/build/lib/searchkit/admin.py,sha256=URZgMKnfKlDqOgmQXJHu7mFGrjwkElpunAUbp2_9JcA,1182
|
47
|
+
build/lib/build/lib/searchkit/apps.py,sha256=17m6wPu5N59Dq4MLoWaQd0aNHEzMT4z4emQD632GIMA,150
|
48
|
+
build/lib/build/lib/searchkit/filters.py,sha256=l8756ftyURUpK3KSkl__TDP5KpqaapxjYMaAjh729ps,1098
|
49
|
+
build/lib/build/lib/searchkit/models.py,sha256=0LEe0z3jOTqAGrqNGknDDY1L1anaG3kCcQ_Zm_7dl9I,800
|
50
|
+
build/lib/build/lib/searchkit/tests.py,sha256=qm8rvKC8aDnaspIXwzCsDwMkfXMR4uOHzqDLWhdv2dA,14849
|
51
|
+
build/lib/build/lib/searchkit/urls.py,sha256=Mhrq4CUOhrh28ZhRocSP2AYnfWFW2c_eJyMR81q5fps,162
|
52
|
+
build/lib/build/lib/searchkit/views.py,sha256=ECSwsge2pD0OJLHdHwpOdWS7XiItUX2NFCO8FSjBigE,919
|
53
|
+
build/lib/build/lib/searchkit/forms/__init__.py,sha256=FBggDa1owkYrceIU3cqNhqsMB49RJWZRAkA4OfvUMcM,207
|
54
|
+
build/lib/build/lib/searchkit/forms/fields.py,sha256=TpFZdAyWKaMhOoZFTuy5ODNrW6RLy289Lk1fcMSGJ20,1621
|
55
|
+
build/lib/build/lib/searchkit/forms/search.py,sha256=mca67piLDqKUhXzaKIOztk5Gg8V1XL21n27aIffH88A,2330
|
56
|
+
build/lib/build/lib/searchkit/forms/searchkit.py,sha256=pg3vw6dMdtaHja-g1Yh72XJkLp7I48nXht9zxWbGW9Y,6022
|
57
|
+
build/lib/build/lib/searchkit/forms/utils.py,sha256=m8vwB-3AoYuMx0QxlJTwSWbDHBG8MyCxFmsyK6xyai8,5221
|
58
|
+
build/lib/build/lib/searchkit/migrations/0001_initial.py,sha256=cP886X1UMrDTf-KxfHfuoQ4b1T1lhdNJyVNOGMNyWNw,1093
|
59
|
+
build/lib/build/lib/searchkit/migrations/0002_rename_searchkitsearch_search.py,sha256=RHXShizf689AdPb2Ca-hONWmwZbB2Fs5DQhXlEPE-f0,389
|
60
|
+
build/lib/build/lib/searchkit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
61
|
+
build/lib/build/lib/searchkit/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
62
|
+
build/lib/build/lib/searchkit/templatetags/searchkit.py,sha256=HpEGTGYi_enDh_bgTgWdVbZftNuZqRt4J9N5A0Nc1AM,581
|
63
|
+
build/lib/example/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
64
|
+
build/lib/example/example/admin.py,sha256=KDjYyHPEqNdv7Xe8yx0VuWdx-bDn7qKKHM5ZYhFwdU0,445
|
65
|
+
build/lib/example/example/asgi.py,sha256=mqLnzcCH9X-8UhDo5ZhcM8tF3jtALEGSjsBmphbkLcs,391
|
66
|
+
build/lib/example/example/models.py,sha256=fB9X782cX01Yg2uIiPCVgrS8C7DkgG9U-9mxGtX3P7Q,1097
|
67
|
+
build/lib/example/example/settings.py,sha256=du9bWbAceSvDkYeNYOc_3KxKL1p1se93TdAueT2RQ_E,3256
|
68
|
+
build/lib/example/example/urls.py,sha256=D8LxjiTdJSA87AVh3BzpVo5E2aC30hlp20HshPDrfvU,800
|
69
|
+
build/lib/example/example/wsgi.py,sha256=OAXHHeNQoj7FBDc5NMET39i_kIGpFrcdNDdY1thrh58,391
|
70
|
+
build/lib/example/example/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
71
|
+
build/lib/example/example/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
72
|
+
build/lib/example/example/management/commands/createtestdata.py,sha256=IVtyUqak133h9Ua-Ag_GP8mw3dUdiDYAa2tGmLkKluU,2737
|
73
|
+
build/lib/example/example/migrations/0001_initial.py,sha256=62tOi17oHGuqqLmSAYWLep6AMkxCJF6Tp13odghS7gI,2014
|
74
|
+
build/lib/example/example/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
75
|
+
build/lib/searchkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
76
|
+
build/lib/searchkit/__version__.py,sha256=g6zhPyD9UelvcYrhtmQjIk-7_RH9Bu2W8YLlyW3M5OM,661
|
77
|
+
build/lib/searchkit/admin.py,sha256=URZgMKnfKlDqOgmQXJHu7mFGrjwkElpunAUbp2_9JcA,1182
|
78
|
+
build/lib/searchkit/apps.py,sha256=17m6wPu5N59Dq4MLoWaQd0aNHEzMT4z4emQD632GIMA,150
|
79
|
+
build/lib/searchkit/filters.py,sha256=l8756ftyURUpK3KSkl__TDP5KpqaapxjYMaAjh729ps,1098
|
80
|
+
build/lib/searchkit/models.py,sha256=0LEe0z3jOTqAGrqNGknDDY1L1anaG3kCcQ_Zm_7dl9I,800
|
81
|
+
build/lib/searchkit/tests.py,sha256=qm8rvKC8aDnaspIXwzCsDwMkfXMR4uOHzqDLWhdv2dA,14849
|
82
|
+
build/lib/searchkit/urls.py,sha256=Mhrq4CUOhrh28ZhRocSP2AYnfWFW2c_eJyMR81q5fps,162
|
83
|
+
build/lib/searchkit/views.py,sha256=ECSwsge2pD0OJLHdHwpOdWS7XiItUX2NFCO8FSjBigE,919
|
84
|
+
build/lib/searchkit/forms/__init__.py,sha256=FBggDa1owkYrceIU3cqNhqsMB49RJWZRAkA4OfvUMcM,207
|
85
|
+
build/lib/searchkit/forms/fields.py,sha256=TpFZdAyWKaMhOoZFTuy5ODNrW6RLy289Lk1fcMSGJ20,1621
|
86
|
+
build/lib/searchkit/forms/search.py,sha256=mca67piLDqKUhXzaKIOztk5Gg8V1XL21n27aIffH88A,2330
|
87
|
+
build/lib/searchkit/forms/searchkit.py,sha256=pg3vw6dMdtaHja-g1Yh72XJkLp7I48nXht9zxWbGW9Y,6022
|
88
|
+
build/lib/searchkit/forms/utils.py,sha256=m8vwB-3AoYuMx0QxlJTwSWbDHBG8MyCxFmsyK6xyai8,5221
|
89
|
+
build/lib/searchkit/migrations/0001_initial.py,sha256=cP886X1UMrDTf-KxfHfuoQ4b1T1lhdNJyVNOGMNyWNw,1093
|
90
|
+
build/lib/searchkit/migrations/0002_rename_searchkitsearch_search.py,sha256=RHXShizf689AdPb2Ca-hONWmwZbB2Fs5DQhXlEPE-f0,389
|
91
|
+
build/lib/searchkit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
92
|
+
build/lib/searchkit/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
93
|
+
build/lib/searchkit/templatetags/searchkit.py,sha256=HpEGTGYi_enDh_bgTgWdVbZftNuZqRt4J9N5A0Nc1AM,581
|
94
|
+
django_searchkit-1.2.dist-info/licenses/LICENCE,sha256=oqmlRYPA5GHG2T1yp8fPFGQdOO-NnJPdGITeFiJYWLg,1521
|
95
|
+
example/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
96
|
+
example/example/admin.py,sha256=KDjYyHPEqNdv7Xe8yx0VuWdx-bDn7qKKHM5ZYhFwdU0,445
|
97
|
+
example/example/asgi.py,sha256=mqLnzcCH9X-8UhDo5ZhcM8tF3jtALEGSjsBmphbkLcs,391
|
98
|
+
example/example/models.py,sha256=fB9X782cX01Yg2uIiPCVgrS8C7DkgG9U-9mxGtX3P7Q,1097
|
99
|
+
example/example/settings.py,sha256=du9bWbAceSvDkYeNYOc_3KxKL1p1se93TdAueT2RQ_E,3256
|
100
|
+
example/example/urls.py,sha256=D8LxjiTdJSA87AVh3BzpVo5E2aC30hlp20HshPDrfvU,800
|
101
|
+
example/example/wsgi.py,sha256=OAXHHeNQoj7FBDc5NMET39i_kIGpFrcdNDdY1thrh58,391
|
102
|
+
example/example/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
103
|
+
example/example/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
104
|
+
example/example/management/commands/createtestdata.py,sha256=IVtyUqak133h9Ua-Ag_GP8mw3dUdiDYAa2tGmLkKluU,2737
|
105
|
+
example/example/migrations/0001_initial.py,sha256=62tOi17oHGuqqLmSAYWLep6AMkxCJF6Tp13odghS7gI,2014
|
106
|
+
example/example/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
107
|
+
searchkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
108
|
+
searchkit/__version__.py,sha256=g6zhPyD9UelvcYrhtmQjIk-7_RH9Bu2W8YLlyW3M5OM,661
|
109
|
+
searchkit/admin.py,sha256=URZgMKnfKlDqOgmQXJHu7mFGrjwkElpunAUbp2_9JcA,1182
|
110
|
+
searchkit/apps.py,sha256=17m6wPu5N59Dq4MLoWaQd0aNHEzMT4z4emQD632GIMA,150
|
111
|
+
searchkit/filters.py,sha256=l8756ftyURUpK3KSkl__TDP5KpqaapxjYMaAjh729ps,1098
|
112
|
+
searchkit/models.py,sha256=0LEe0z3jOTqAGrqNGknDDY1L1anaG3kCcQ_Zm_7dl9I,800
|
113
|
+
searchkit/tests.py,sha256=qm8rvKC8aDnaspIXwzCsDwMkfXMR4uOHzqDLWhdv2dA,14849
|
114
|
+
searchkit/urls.py,sha256=Mhrq4CUOhrh28ZhRocSP2AYnfWFW2c_eJyMR81q5fps,162
|
115
|
+
searchkit/views.py,sha256=ECSwsge2pD0OJLHdHwpOdWS7XiItUX2NFCO8FSjBigE,919
|
116
|
+
searchkit/forms/__init__.py,sha256=FBggDa1owkYrceIU3cqNhqsMB49RJWZRAkA4OfvUMcM,207
|
117
|
+
searchkit/forms/fields.py,sha256=TpFZdAyWKaMhOoZFTuy5ODNrW6RLy289Lk1fcMSGJ20,1621
|
118
|
+
searchkit/forms/search.py,sha256=mca67piLDqKUhXzaKIOztk5Gg8V1XL21n27aIffH88A,2330
|
119
|
+
searchkit/forms/searchkit.py,sha256=pg3vw6dMdtaHja-g1Yh72XJkLp7I48nXht9zxWbGW9Y,6022
|
120
|
+
searchkit/forms/utils.py,sha256=m8vwB-3AoYuMx0QxlJTwSWbDHBG8MyCxFmsyK6xyai8,5221
|
121
|
+
searchkit/migrations/0001_initial.py,sha256=cP886X1UMrDTf-KxfHfuoQ4b1T1lhdNJyVNOGMNyWNw,1093
|
122
|
+
searchkit/migrations/0002_rename_searchkitsearch_search.py,sha256=RHXShizf689AdPb2Ca-hONWmwZbB2Fs5DQhXlEPE-f0,389
|
123
|
+
searchkit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
124
|
+
searchkit/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
125
|
+
searchkit/templatetags/searchkit.py,sha256=HpEGTGYi_enDh_bgTgWdVbZftNuZqRt4J9N5A0Nc1AM,581
|
126
|
+
django_searchkit-1.2.dist-info/METADATA,sha256=uKoqf1iEWc63SpPhb3cRFIvfY9_J3ziOoPgazA8Dn_w,3325
|
127
|
+
django_searchkit-1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
128
|
+
django_searchkit-1.2.dist-info/top_level.txt,sha256=-4gF42VIaG-ckn2rb2wFa7LhxIZymHBsYVedNOr_NIY,29
|
129
|
+
django_searchkit-1.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
130
|
+
django_searchkit-1.2.dist-info/RECORD,,
|
example/example/admin.py
CHANGED
@@ -7,7 +7,7 @@ from .models import ModelB
|
|
7
7
|
@admin.register(ModelA)
|
8
8
|
class ModelAAdmin(admin.ModelAdmin):
|
9
9
|
list_display = [f.name for f in ModelA._meta.fields]
|
10
|
-
list_filter = [SearchkitFilter
|
10
|
+
list_filter = [SearchkitFilter]
|
11
11
|
|
12
12
|
|
13
13
|
@admin.register(ModelB)
|
searchkit/__version__.py
CHANGED