django-searchkit 1.0__py3-none-any.whl → 1.1__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.
Files changed (65) hide show
  1. build/lib/build/lib/example/example/__init__.py +0 -0
  2. build/lib/build/lib/example/example/admin.py +16 -0
  3. build/lib/build/lib/example/example/asgi.py +16 -0
  4. build/lib/build/lib/example/example/management/__init__.py +0 -0
  5. build/lib/build/lib/example/example/management/commands/__init__.py +0 -0
  6. build/lib/build/lib/example/example/management/commands/createtestdata.py +62 -0
  7. build/lib/build/lib/example/example/migrations/0001_initial.py +48 -0
  8. build/lib/build/lib/example/example/migrations/__init__.py +0 -0
  9. build/lib/build/lib/example/example/models.py +38 -0
  10. build/lib/build/lib/example/example/settings.py +125 -0
  11. build/lib/build/lib/example/example/urls.py +23 -0
  12. build/lib/build/lib/example/example/wsgi.py +16 -0
  13. build/lib/build/lib/searchkit/__init__.py +0 -0
  14. build/lib/build/lib/searchkit/__version__.py +16 -0
  15. build/lib/build/lib/searchkit/admin.py +30 -0
  16. build/lib/build/lib/searchkit/apps.py +6 -0
  17. build/lib/build/lib/searchkit/filters.py +27 -0
  18. build/lib/build/lib/searchkit/forms/__init__.py +5 -0
  19. build/lib/build/lib/searchkit/forms/fields.py +55 -0
  20. build/lib/build/lib/searchkit/forms/search.py +62 -0
  21. build/lib/build/lib/searchkit/forms/searchkit.py +154 -0
  22. build/lib/build/lib/searchkit/forms/utils.py +178 -0
  23. build/lib/build/lib/searchkit/migrations/0001_initial.py +30 -0
  24. build/lib/build/lib/searchkit/migrations/0002_rename_searchkitsearch_search.py +18 -0
  25. build/lib/build/lib/searchkit/migrations/__init__.py +0 -0
  26. build/lib/build/lib/searchkit/models.py +27 -0
  27. build/lib/build/lib/searchkit/templatetags/__init__.py +0 -0
  28. build/lib/build/lib/searchkit/templatetags/searchkit.py +20 -0
  29. build/lib/build/lib/searchkit/tests.py +402 -0
  30. build/lib/build/lib/searchkit/urls.py +7 -0
  31. build/lib/build/lib/searchkit/views.py +23 -0
  32. build/lib/searchkit/__version__.py +1 -1
  33. build/lib/searchkit/admin.py +4 -4
  34. build/lib/searchkit/filters.py +7 -11
  35. build/lib/searchkit/forms/__init__.py +5 -3
  36. build/lib/searchkit/forms/search.py +37 -17
  37. build/lib/searchkit/forms/searchkit.py +60 -95
  38. build/lib/searchkit/forms/utils.py +44 -15
  39. build/lib/searchkit/migrations/0002_rename_searchkitsearch_search.py +18 -0
  40. build/lib/searchkit/models.py +8 -4
  41. build/lib/searchkit/templatetags/searchkit.py +0 -27
  42. build/lib/searchkit/tests.py +201 -49
  43. build/lib/searchkit/urls.py +1 -2
  44. build/lib/searchkit/views.py +11 -18
  45. {django_searchkit-1.0.dist-info → django_searchkit-1.1.dist-info}/METADATA +9 -24
  46. django_searchkit-1.1.dist-info/RECORD +99 -0
  47. example/example/admin.py +1 -1
  48. searchkit/__version__.py +1 -1
  49. searchkit/admin.py +4 -4
  50. searchkit/filters.py +7 -11
  51. searchkit/forms/__init__.py +5 -3
  52. searchkit/forms/search.py +37 -17
  53. searchkit/forms/searchkit.py +60 -95
  54. searchkit/forms/utils.py +44 -15
  55. searchkit/migrations/0002_rename_searchkitsearch_search.py +18 -0
  56. searchkit/models.py +8 -4
  57. searchkit/templatetags/searchkit.py +0 -27
  58. searchkit/tests.py +201 -49
  59. searchkit/urls.py +1 -2
  60. searchkit/views.py +11 -18
  61. django_searchkit-1.0.dist-info/RECORD +0 -66
  62. {django_searchkit-1.0.dist-info → django_searchkit-1.1.dist-info}/WHEEL +0 -0
  63. {django_searchkit-1.0.dist-info → django_searchkit-1.1.dist-info}/licenses/LICENCE +0 -0
  64. {django_searchkit-1.0.dist-info → django_searchkit-1.1.dist-info}/top_level.txt +0 -0
  65. {django_searchkit-1.0.dist-info → django_searchkit-1.1.dist-info}/zip-safe +0 -0
searchkit/filters.py CHANGED
@@ -1,8 +1,6 @@
1
1
  from django.contrib.admin import SimpleListFilter
2
2
  from django.contrib.contenttypes.models import ContentType
3
- from .models import SearchkitSearch
4
- from .forms import SearchkitFormSet
5
- from .forms.utils import get_filter_rules
3
+ from .models import Search
6
4
 
7
5
 
8
6
  class SearchkitFilter(SimpleListFilter):
@@ -11,21 +9,19 @@ class SearchkitFilter(SimpleListFilter):
11
9
  template = 'searchkit/searchkit_filter.html'
12
10
 
13
11
  def __init__(self, request, params, model, model_admin):
14
- # We need the app_label and model_name for the reverse url lookup in the
15
- # template.
16
- self.app_label = model._meta.app_label
17
- self.model_name = model._meta.model_name
12
+ # We need the app_label and model as get parameter for the new search
13
+ # link.
14
+ self.searchkit_model = ContentType.objects.get_for_model(model)
18
15
  super().__init__(request, params, model, model_admin)
19
16
 
20
17
  def lookups(self, request, model_admin):
21
18
  # Fetch the last three objects from SearchkitSearch and return them as
22
19
  # choices.
23
- ct = ContentType.objects.get_for_model(model_admin.model)
24
- searches = SearchkitSearch.objects.filter(contenttype=ct).order_by('-created_date')[:3]
20
+ searches = Search.objects.filter(contenttype=self.searchkit_model).order_by('-created_date')[:3]
25
21
  return [(str(obj.id), obj.name) for obj in searches]
26
22
 
27
23
  def queryset(self, request, queryset):
28
24
  # Filter the queryset based on the selected SearchkitSearch object
29
25
  if self.value():
30
- search = SearchkitSearch.objects.get(id=int(self.value()))
31
- return queryset.filter(**search.get_filter_rules())
26
+ search = Search.objects.get(id=int(self.value()))
27
+ return search.as_queryset()
@@ -1,3 +1,5 @@
1
- from .search import SearchkitSearchForm
2
- from .searchkit import SearchkitFormSet
3
- from .searchkit import SearchkitForm
1
+ from .search import SearchForm
2
+ from .searchkit import SearchkitModelForm
3
+ from .searchkit import BaseSearchkitFormSet
4
+ from .searchkit import BaseSearchkitForm
5
+ from .searchkit import searchkit_formset_factory
searchkit/forms/search.py CHANGED
@@ -1,22 +1,40 @@
1
1
  from django import forms
2
2
  from django.utils.functional import cached_property
3
- from ..models import SearchkitSearch
4
- from .searchkit import SearchkitFormSet
3
+ from django.contrib.contenttypes.models import ContentType
4
+ from ..models import Search
5
+ from .searchkit import SearchkitModelForm
6
+ from .searchkit import searchkit_formset_factory
7
+ from .utils import MediaMixin
5
8
 
6
9
 
7
- class SearchkitSearchForm(forms.ModelForm):
10
+ class SearchForm(MediaMixin, forms.ModelForm):
8
11
  """
9
12
  Represents a SearchkitSearch model. Using a SearchkitFormSet for the data
10
13
  json field.
11
14
  """
12
15
  class Meta:
13
- model = SearchkitSearch
16
+ model = Search
14
17
  fields = ['name']
15
18
 
16
- @property
17
- def media(self):
18
- # TODO: Check if child classes inherit those media files.
19
- return self.formset.media
19
+ @cached_property
20
+ def searchkit_model(self):
21
+ if self.instance.pk:
22
+ return self.instance.contenttype.model_class()
23
+ elif self.searchkit_model_form.is_valid():
24
+ return self.searchkit_model_form.cleaned_data['searchkit_model'].model_class()
25
+ elif 'searchkit_model' in self.searchkit_model_form.initial:
26
+ value = self.searchkit_model_form.initial['searchkit_model']
27
+ try:
28
+ return self.searchkit_model_form.fields['searchkit_model'].clean(value).model_class()
29
+ except forms.ValidationError:
30
+ return None
31
+
32
+ @cached_property
33
+ def searchkit_model_form(self):
34
+ kwargs = dict(data=self.data or None, initial=self.initial or None)
35
+ if self.instance.pk:
36
+ kwargs['initial'] = dict(searchkit_model=self.instance.contenttype)
37
+ return SearchkitModelForm(**kwargs)
20
38
 
21
39
  @cached_property
22
40
  def formset(self):
@@ -24,19 +42,21 @@ class SearchkitSearchForm(forms.ModelForm):
24
42
  A searchkit formset for the model.
25
43
  """
26
44
  kwargs = dict()
27
- kwargs['data'] = self.data or None
28
- kwargs['prefix'] = self.prefix
29
- if self.instance.pk:
30
- kwargs['model'] = self.instance.contenttype.model_class()
31
- kwargs['initial'] = self.instance.data
32
- return SearchkitFormSet(**kwargs)
45
+ if self.searchkit_model and self.data:
46
+ kwargs = dict(data=self.data)
47
+ elif self.searchkit_model and self.instance.pk:
48
+ kwargs = dict(initial=self.instance.data)
49
+
50
+ extra = 0 if self.instance.pk else 1
51
+ formset = searchkit_formset_factory(model=self.searchkit_model, extra=extra)
52
+ return formset(**kwargs)
33
53
 
34
54
  def is_valid(self):
35
- return self.formset.is_valid() and super().is_valid()
55
+ return self.formset.is_valid() and self.searchkit_model_form.is_valid and super().is_valid()
36
56
 
37
57
  def clean(self):
38
- if self.formset.contenttype_form.is_valid():
39
- self.instance.contenttype = self.formset.contenttype_form.cleaned_data['contenttype']
58
+ if self.searchkit_model_form.is_valid():
59
+ self.instance.contenttype = self.searchkit_model_form.cleaned_data['searchkit_model']
40
60
  if self.formset.is_valid():
41
61
  self.instance.data = self.formset.cleaned_data
42
62
  return super().clean()
@@ -1,17 +1,29 @@
1
- from collections import OrderedDict
2
1
  from django import forms
3
2
  from django.utils.translation import gettext_lazy as _
4
3
  from django.utils.functional import cached_property
5
- from django.contrib.contenttypes.models import ContentType
6
- from .utils import CSS_CLASSES, FIELD_PLAN, OPERATOR_DESCRIPTION
7
- from .utils import SUPPORTED_FIELDS, SUPPORTED_RELATIONS
4
+ from .utils import CssClassMixin, FIELD_PLAN, OPERATOR_DESCRIPTION
5
+ from .utils import SUPPORTED_FIELDS
6
+ from .utils import ModelTree
7
+ from .utils import MediaMixin
8
+ from .utils import get_searchable_models
8
9
 
9
10
 
10
- # FIXME: Make this a setting
11
- RELATION_DEPTH = 3
11
+ class SearchkitModelForm(forms.Form):
12
+ """
13
+ Form to select a content type.
14
+ """
15
+ searchkit_model = forms.ModelChoiceField(
16
+ queryset=get_searchable_models(),
17
+ label=_('Model'),
18
+ empty_label=_('Select a Model'),
19
+ widget=forms.Select(attrs={
20
+ "class": CssClassMixin.reload_on_change_css_class,
21
+ "data-total-forms": 1,
22
+ }),
23
+ )
12
24
 
13
25
 
14
- class SearchkitForm(CSS_CLASSES, forms.Form):
26
+ class BaseSearchkitForm(MediaMixin, CssClassMixin, forms.Form):
15
27
  """
16
28
  Searchkit form representing a model field lookup based on the field name,
17
29
  the operator and one or two values.
@@ -24,9 +36,11 @@ class SearchkitForm(CSS_CLASSES, forms.Form):
24
36
 
25
37
  See the FIELD_PLAN variable for the logic of building the form.
26
38
  """
27
- def __init__(self, model, *args, **kwargs):
39
+ model = None # Set by the formset factory.
40
+
41
+ def __init__(self, *args, **kwargs):
28
42
  super().__init__(*args, **kwargs)
29
- self.model = model
43
+ self.model_tree = ModelTree(self.model)
30
44
  self.model_field = None
31
45
  self.field_plan = None
32
46
  self.operator = None
@@ -64,40 +78,44 @@ class SearchkitForm(CSS_CLASSES, forms.Form):
64
78
 
65
79
  def _get_model_field(self, lookup):
66
80
  path = lookup.split('__')
67
- model = self.model
68
- for index, field_name in enumerate(path, 1):
69
- field = model._meta.get_field(field_name)
70
- if index < len(path):
71
- model = field.remote_field.model
72
- return field
73
-
74
- def _get_model_field_choices(self, model, fields=[]):
81
+ field_name = path[-1]
82
+ if path[:-1]:
83
+ model = self.model_tree.get('__'.join(path[:-1])).model
84
+ else:
85
+ model = self.model
86
+ return model._meta.get_field(field_name)
87
+
88
+ def _get_model_field_choices(self):
75
89
  choices = list()
76
- for model_field in model._meta.fields:
77
- if any(isinstance(model_field, f) for f in SUPPORTED_FIELDS):
78
- lookup = '__'.join([f.name for f in [*fields, model_field]])
79
- label = ' -> '.join(f.verbose_name for f in [*fields, model_field])
90
+ label_path = list()
91
+ for node in self.model_tree.iterate():
92
+ label_path.append
93
+ for model_field in node.model._meta.fields:
94
+ if not any(isinstance(model_field, f) for f in SUPPORTED_FIELDS):
95
+ continue
96
+ if node.is_root:
97
+ lookup = model_field.name
98
+ label = f'`{model_field.verbose_name}`'
99
+ else:
100
+ lookup = f'{node.field_path}__{model_field.name}'
101
+ get_field_name = lambda f: getattr(f, 'verbose_name', f.name)
102
+ label_path = [f'`{get_field_name(n.field)}` => <{n.model._meta.verbose_name}>' for n in node.path[1:]]
103
+ label = ".".join(label_path + [f'`{model_field.verbose_name}`'])
80
104
  choices.append((lookup, label))
81
- if len(fields) < RELATION_DEPTH:
82
- for model_field in model._meta.fields:
83
- if any(isinstance(model_field, f) for f in SUPPORTED_RELATIONS):
84
- related_model = model_field.remote_field.model
85
- fields = [*fields, model_field]
86
- choices += self._get_model_field_choices(related_model, fields)
87
105
  return choices
88
106
 
89
107
  def _add_field_name_field(self):
90
108
  initial = self.initial.get('field')
91
- choices = self._get_model_field_choices(self.model)
109
+ choices = self._get_model_field_choices()
92
110
  field = forms.ChoiceField(label=_('Model field'), choices=choices, initial=initial)
93
- field.widget.attrs.update({"class": CSS_CLASSES.reload_on_change_css_class})
111
+ field.widget.attrs.update({"class": self.reload_on_change_css_class})
94
112
  self.fields['field'] = field
95
113
 
96
114
  def _add_operator_field(self):
97
115
  initial = self.initial.get('operator')
98
116
  choices = [(o, OPERATOR_DESCRIPTION[o]) for o in self.field_plan.keys()]
99
117
  field = forms.ChoiceField(label=_('Operator'), choices=choices, initial=initial)
100
- field.widget.attrs.update({"class": CSS_CLASSES.reload_on_change_css_class})
118
+ field.widget.attrs.update({"class": self.reload_on_change_css_class})
101
119
  self.fields['operator'] = field
102
120
 
103
121
  def _add_value_field(self):
@@ -110,80 +128,27 @@ class SearchkitForm(CSS_CLASSES, forms.Form):
110
128
  self.fields['value'] = field
111
129
 
112
130
 
113
- class ContentTypeForm(CSS_CLASSES, forms.Form):
114
- """
115
- Form to select a content type.
116
- """
117
- contenttype = forms.ModelChoiceField(
118
- queryset=ContentType.objects.all(), # FIXME: Limit choices to models that can be filtered.
119
- label=_('Model'),
120
- empty_label=_('Select a Model'),
121
- widget=forms.Select(attrs={"class": CSS_CLASSES.reload_on_change_css_class}),
122
- )
123
-
124
- class Media:
125
- js = [
126
- 'admin/js/vendor/jquery/jquery.min.js',
127
- 'admin/js/jquery.init.js',
128
- "searchkit/searchkit.js"
129
- ]
130
-
131
-
132
- class BaseSearchkitFormset(CSS_CLASSES, forms.BaseFormSet):
131
+ class BaseSearchkitFormSet(CssClassMixin, forms.BaseFormSet):
133
132
  """
134
133
  Formset holding all searchkit forms.
135
134
  """
136
135
  template_name = "searchkit/searchkit.html"
137
136
  template_name_div = "searchkit/searchkit.html"
138
- default_prefix = 'searchkit'
139
- form = SearchkitForm
140
- contenttype_form_class = ContentTypeForm
141
-
142
- def __init__(self, *args, **kwargs):
143
- self.model = kwargs.pop('model', None)
144
- super().__init__(*args, **kwargs)
145
- self.contenttype_form = self.get_conttenttype_form(kwargs)
146
- if not self.model and self.contenttype_form.is_valid():
147
- self.model = self.contenttype_form.cleaned_data.get('contenttype').model_class()
148
- if self.initial:
149
- self.extra = 0
150
-
151
- def get_conttenttype_form(self, kwargs):
152
- ct_kwargs = dict()
153
- ct_kwargs['data'] = self.data or None
154
- ct_kwargs['prefix'] = self.prefix
155
- if self.model:
156
- contenttype = ContentType.objects.get_for_model(self.model)
157
- ct_kwargs['initial'] = dict(contenttype=contenttype)
158
- return self.contenttype_form_class(**ct_kwargs)
159
-
160
- def get_form_kwargs(self, index):
161
- kwargs = self.form_kwargs.copy()
162
- kwargs['model'] = self.model
163
- return kwargs
137
+ model = None # Set by the formset factory.
164
138
 
165
139
  def add_prefix(self, index):
166
- if self.model:
167
- return "%s-%s-%s" % (self.prefix, self.model._meta.model_name, index)
140
+ return "%s-%s-%s-%s" % (self.prefix, self.model._meta.app_label, self.model._meta.model_name, index)
168
141
 
169
142
  @classmethod
170
- def get_default_prefix(cls):
171
- return cls.default_prefix
172
-
173
- @cached_property
174
- def forms(self):
175
- # We won't render any forms if we got no model.
176
- return super().forms if self.model else []
177
-
178
- @property
179
- def media(self):
180
- return self.contenttype_form.media
181
-
182
- def is_valid(self):
183
- return self.contenttype_form.is_valid() and self.forms and super().is_valid()
143
+ def get_default_prefix(self):
144
+ return "searchkit"
184
145
 
185
146
 
186
- SearchkitFormSet = forms.formset_factory(
187
- form=SearchkitForm,
188
- formset=BaseSearchkitFormset,
147
+ def searchkit_formset_factory(model, **kwargs):
148
+ form = type('SearchkitForm', (BaseSearchkitForm,), dict(model=model))
149
+ formset = type('SearchkitFormSet', (BaseSearchkitFormSet,), dict(model=model))
150
+ return forms.formset_factory(
151
+ form=form,
152
+ formset=formset,
153
+ **kwargs
189
154
  )
searchkit/forms/utils.py CHANGED
@@ -1,8 +1,23 @@
1
+ from modeltree import ModelTree as BaseModelTree
2
+ from collections import OrderedDict
3
+ from django.apps import apps
4
+ from django.contrib import admin
5
+ from django.contrib.contenttypes.models import ContentType
1
6
  from django.db import models
7
+ from django.db.utils import OperationalError
2
8
  from django import forms
3
9
  from django.utils.translation import gettext_lazy as _
4
- from collections import OrderedDict
5
- from searchkit.forms import fields as searchkit_fields
10
+ from ..filters import SearchkitFilter
11
+ from . import fields as searchkit_fields
12
+
13
+
14
+ class ModelTree(BaseModelTree):
15
+ MAX_DEPTH = 3
16
+ FOLLOW_ACROSS_APPS = True
17
+ RELATION_TYPES = [
18
+ 'one_to_one',
19
+ 'many_to_one',
20
+ ]
6
21
 
7
22
 
8
23
  OPERATOR_DESCRIPTION = {
@@ -29,10 +44,6 @@ SUPPORTED_FIELDS = [
29
44
  models.DateField,
30
45
  models.DateTimeField,
31
46
  ]
32
- SUPPORTED_RELATIONS = [
33
- models.ForeignKey,
34
- models.OneToOneField,
35
- ]
36
47
 
37
48
 
38
49
  FIELD_PLAN = OrderedDict((
@@ -132,18 +143,36 @@ FIELD_PLAN = OrderedDict((
132
143
  ))
133
144
 
134
145
 
135
- class CSS_CLASSES:
146
+ class CssClassMixin:
136
147
  reload_on_change_css_class = "searchkit-reload-on-change"
137
148
  reload_on_click_css_class = "searchkit-reload-on-click"
138
149
 
139
150
 
140
- def get_filter_rules(formset):
151
+ class MediaMixin:
152
+ class Media:
153
+ js = [
154
+ 'admin/js/vendor/jquery/jquery.min.js',
155
+ 'admin/js/jquery.init.js',
156
+ "searchkit/searchkit.js"
157
+ ]
158
+
159
+
160
+ def is_searchable_model(model):
161
+ """
162
+ Check if the model is searchable by Searchkit.
163
+ """
164
+ return admin.site.is_registered(model) and SearchkitFilter in admin.site._registry[model].list_filter
165
+
166
+
167
+ def get_searchable_models():
141
168
  """
142
- Build filter rules out of the cleaned data of the formset.
143
- :param formset: Formset to extract filter rules from.
144
- :return: OrderedDict with filter rule pairs: field__operator: value
169
+ Return a queryset of searchable models.
145
170
  """
146
- lookups = OrderedDict()
147
- for data in formset.cleaned_data:
148
- lookups[f'{data["field"]}__{data["operator"]}'] = data['value']
149
- return lookups
171
+ # Before mirating the database we get an OperationalError when trying to
172
+ # access ContentType database table.
173
+ try:
174
+ models = [m for m in apps.get_models() if is_searchable_model(m)]
175
+ ids = [ContentType.objects.get_for_model(m).id for m in models]
176
+ return ContentType.objects.filter(pk__in=ids).order_by('app_label', 'model')
177
+ except OperationalError:
178
+ return ContentType.objects.all()
@@ -0,0 +1,18 @@
1
+ # Generated by Django 5.1.3 on 2025-06-07 05:46
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('contenttypes', '0002_remove_content_type_name'),
10
+ ('searchkit', '0001_initial'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.RenameModel(
15
+ old_name='SearchkitSearch',
16
+ new_name='Search',
17
+ ),
18
+ ]
searchkit/models.py CHANGED
@@ -5,9 +5,7 @@ from django.contrib.contenttypes.models import ContentType
5
5
  from django.utils.translation import gettext_lazy as _
6
6
 
7
7
 
8
- # Create your models here.
9
- # TODO: Use pickled cleaned data with a char field.
10
- class SearchkitSearch(models.Model):
8
+ class Search(models.Model):
11
9
  name = models.CharField(_('Search name'), max_length=255)
12
10
  contenttype = models.ForeignKey(ContentType, on_delete=models.CASCADE, verbose_name=_('Model'))
13
11
  data = PickledObjectField(_('Serialized filter rule data'))
@@ -16,8 +14,14 @@ class SearchkitSearch(models.Model):
16
14
  class Meta:
17
15
  unique_together = ('name', 'contenttype')
18
16
 
19
- def get_filter_rules(self):
17
+ def as_lookups(self):
20
18
  lookups = OrderedDict()
21
19
  for data in self.data:
22
20
  lookups[f'{data["field"]}__{data["operator"]}'] = data['value']
23
21
  return lookups
22
+
23
+ def as_queryset(self):
24
+ """
25
+ Returns a filtered queryset for the model.
26
+ """
27
+ return self.contenttype.model_class().objects.filter(**self.as_lookups())
@@ -1,36 +1,9 @@
1
1
  from django.template import Library
2
- from django.urls import reverse
3
2
  from django.contrib.admin.helpers import Fieldset
4
- from ..forms.utils import CSS_CLASSES
5
3
 
6
4
 
7
5
  register = Library()
8
6
 
9
-
10
- @register.simple_tag
11
- def searchkit_url(formset):
12
- """
13
- Return url to reload the formset.
14
- """
15
- app_label = formset.model._meta.app_label
16
- model_name = formset.model._meta.model_name
17
- url = reverse('searchkit_form', args=[app_label, model_name])
18
- return url
19
-
20
- @register.simple_tag
21
- def on_change_class():
22
- """
23
- Return css class for on change handler.
24
- """
25
- return CSS_CLASSES.reload_on_change_css_class
26
-
27
- @register.simple_tag
28
- def on_click_class():
29
- """
30
- Return css class for on click handler.
31
- """
32
- return CSS_CLASSES.reload_on_click_css_class
33
-
34
7
  @register.inclusion_tag("admin/includes/fieldset.html")
35
8
  def as_fieldset(form, heading_level=2, prefix='', id_prefix=0, id_suffix='', **fieldset_kwargs):
36
9
  """