Django custom select widgets for select2 js
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)
|