1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 | from django.forms.widgets import Select, SelectMultiple
from django.utils.safestring import mark_safe
class CustomSelectWithQueryset(Select):
'''
Works with ModelChoiceField
'''
def __init__(self, queryset=None, attrs=None, choices=(), ajax_url=None):
super().__init__(attrs=attrs, choices=choices)
self.queryset = queryset
self.ajax_url = ajax_url
def render(self, name, value, attrs=None, renderer=None):
if attrs is None:
attrs = {}
# Set the id attribute based on the field name
attrs['id'] = f'id_{name}'
# Generate options from the queryset
if self.queryset is not None:
choices = [(obj.pk, str(obj)) for obj in self.queryset]
else:
choices = self.choices
self.choices = choices
print(self.choices)
output = super().render(name, value, attrs, renderer)
ajax_url = self.ajax_url
# Add the Select2 initialization script
script = f'''
<script type="text/javascript">
(function($) {{
$(document).ready(function() {{
$('#{attrs['id']}').select2({{
ajax: {{
url: '{ajax_url}',
dataType: 'json',
delay: 250,
data: function (params) {{
return {{
search: params.term,
type: 'public'
}};
}},
processResults: function (data) {{
return {{
results: $.map(data.results, function (item) {{
return {{
id: item.id,
text: item.text
}};
}})
}};
}},
cache: true
}},
placeholder: "Select option",
allowClear: true,
}});
}});
}})(jQuery);
</script>
'''
return mark_safe(output + script)
class CustomSelectMultipleWithUrl(SelectMultiple):
'''
Works with ModelMultipleChoiceField
'''
def __init__(self, queryset=None, attrs=None, choices=(), ajax_url=None):
super().__init__(attrs=attrs, choices=choices)
self.queryset = queryset
self.ajax_url = ajax_url
def render(self, name, value, attrs=None, renderer=None):
if attrs is None:
attrs = {}
# Set the id attribute based on the field name
attrs['id'] = f'id_{name}'
# Generate options from the queryset
if self.queryset is not None:
choices = [(obj.pk, str(obj)) for obj in self.queryset]
else:
choices = self.choices
self.choices = choices
output = super().render(name, value, attrs, renderer)
# Add the Select2 initialization script with dynamic AJAX URL
ajax_url = self.ajax_url
script = f'''
<script type="text/javascript">
(function($) {{
$(document).ready(function() {{
$('#{attrs['id']}').select2({{
ajax: {{
url: '{ajax_url}',
dataType: 'json',
delay: 250,
data: function (params) {{
return {{
search: params.term,
type: 'public'
}};
}},
processResults: function (data) {{
return {{
results: $.map(data.results, function (item) {{
return {{
id: item.id,
text: item.text
}};
}})
}};
}},
cache: true
}},
placeholder: "Select options",
allowClear: true,
multiple: true // Enable multiple selection
}});
}});
}})(jQuery);
</script>
'''
return mark_safe(output + script)
|