Widgets Overview¶
Django Gentelella Widgets provides a comprehensive set of form widgets that replace Django’s default widgets with Bootstrap 5 styled, feature-rich alternatives.
Quick Start¶
Import widgets from the core module:
from djgentelella.widgets import core as genwidgets
Use them in your forms:
from django import forms
from djgentelella.forms.forms import GTForm
from djgentelella.widgets import core as genwidgets
class MyForm(GTForm, forms.Form):
name = forms.CharField(widget=genwidgets.TextInput)
email = forms.EmailField(widget=genwidgets.EmailInput)
birth_date = forms.DateField(widget=genwidgets.DateInput)
Or with ModelForm:
class MyModelForm(GTForm, forms.ModelForm):
class Meta:
model = MyModel
fields = ['name', 'email', 'country', 'description']
widgets = {
'name': genwidgets.TextInput,
'email': genwidgets.EmailInput,
'country': genwidgets.Select,
'description': genwidgets.Textarea,
}
Widget Categories¶
Core Inputs (djgentelella.widgets.core)
TextInput- Text input fieldNumberInput- Integer inputFloatInput- Decimal inputEmailInput- Email fieldURLInput- URL fieldPasswordInput- Password fieldHiddenInput- Hidden fieldColorInput- Color pickerTextarea- Multi-line text
Select Widgets (djgentelella.widgets.core)
Select- Single select dropdown (Select2)SelectMultiple- Multi-select dropdownSelectWithAdd- Select with add new optionSelectMultipleAdd- Multi-select with add newRadioHorizontalSelect/RadioVerticalSelect- Radio buttonsNullBooleanSelect- Yes/No/UnknownCheckboxInput- Single checkboxCheckboxSelectMultiple- Multiple checkboxesFilteredSelectMultiple(djgentelella.widgets.selectmultiple) - Two panel available/chosen picker, thefilter_horizontallayout
Date/Time Widgets (djgentelella.widgets.core)
DateInput- Date pickerDateTimeInput- DateTime pickerTimeInput- Time pickerDateRangeInput- Date range selectorDateRangeInputCustom- Date range with presetsDateRangeTimeInput- DateTime rangeSplitDateTimeWidget- Separate date/time inputsSelectDateWidget- Dropdown date selector
Masked Inputs (djgentelella.widgets.core)
EmailMaskInput- Email with maskPhoneNumberMaskInput- Phone with maskDateMaskInput- Date with maskCreditCardMaskInput- Credit card formatTaxIDMaskInput- Tax ID formatSerialNumberMaskInput- Serial number format
File Widgets (djgentelella.widgets.core and djgentelella.widgets.files)
FileInput- File upload with chunkingClearableFileInput- File with clear optionFileChunkedUpload- Large file uploadImageRecordInput- Camera captureVideoRecordInput- Video recordingAudioRecordInput- Audio recording
Autocomplete Widgets (djgentelella.widgets.selects)
AutocompleteSelect- Single select with remote searchAutocompleteSelectMultiple- Multi-select with remote searchAutocompleteSelectImage- Image selectionAutocompleteSelectMultipleImage- Multiple image selection
Slider Widgets (djgentelella.widgets.core)
GridSlider- Range sliderSingleGridSlider- Single value sliderDateGridSlider- Date range slider
Special Widgets
YesNoInput- Toggle with field visibility controlNumberKnobInput- Circular knob input (djgentelella.widgets.numberknob)TaggingInput/EmailTaggingInput- Tag inputs (djgentelella.widgets.tagging)EditorTinymce- WYSIWYG editor (djgentelella.widgets.tinymce)CalendarInput- Calendar widget (djgentelella.widgets.calendar)DigitalSignatureInput- Digital signature (djgentelella.widgets.digital_signature)
Voice Widgets (speech-to-text dictation, see Voice dictation widgets)
VoiceDictation- Textarea with progressive voice dictation (djgentelella.widgets.core)VoiceEditorTinymce- TinyMCE editor with voice dictation (djgentelella.widgets.tinymce)
Map Widgets (Leaflet, see Map widgets)
MapPointInput- Pick a GPS point on a map (djgentelella.widgets.maps)DJMap- Dashboard map fed by an API (gentelella/widgets/djmap.html)
Visualization Widgets (readonly display)
UrlTimeLineInput- Timeline display (djgentelella.widgets.timeline)UrlStoryLineInput- Storyline display (djgentelella.widgets.storyline)MapBasedStoryMapInput- Map story (djgentelella.widgets.storymap)GigaPixelStoryMapInput- High-res image story (djgentelella.widgets.storymap)
Tree Widgets (djgentelella.widgets.trees)
TreeSelect- Hierarchical single selectTreeSelectMultiple- Hierarchical multi-selectTreeSelectWithAdd- Tree select with add newTreeSelectMultipleWithAdd- Tree multi-select with add new
Passing Attributes¶
All widgets accept an attrs parameter for HTML attributes:
class MyForm(GTForm, forms.Form):
name = forms.CharField(
widget=genwidgets.TextInput(attrs={
'placeholder': 'Enter your name',
'class': 'custom-class',
'data-custom': 'value',
'maxlength': 100,
})
)
Common attributes:
placeholder- Placeholder textclass- Additional CSS classesdata-*- Custom data attributes for JavaScriptdisabled- Disable the inputreadonly- Make read-only
API Reference¶
Core Widgets¶
- class djgentelella.widgets.core.AudioRecordInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.CheckboxInput(attrs=None)¶
- class djgentelella.widgets.core.ClearableFileInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.ColorInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.CreditCardMaskInput(attrs=None, format=None)¶
- class djgentelella.widgets.core.DateInput(attrs=None, format=None)¶
Warning
Set in settings
USE_L10N = False
DATE_INPUT_FORMATS=[ ‘%Y-%m-%d’,’%d/%m/%Y’,’%d/%m/%y’]
By limitation on js datetime widget format conversion
- class djgentelella.widgets.core.DateMaskInput(attrs=None)¶
- class djgentelella.widgets.core.DateRangeInput(attrs=None, format=None)¶
- class djgentelella.widgets.core.DateRangeInputCustom(attrs=None, format=None)¶
- class djgentelella.widgets.core.DateRangeTimeInput(attrs=None, format=None)¶
- class djgentelella.widgets.core.DateTimeInput(attrs=None, format=None)¶
Warning
Set in settings
USE_L10N = False
DATETIME_INPUT_FORMATS=[ ‘%m/%d/%Y %H:%M %p’ ]
By limitation on js datetime widget format conversion
- class djgentelella.widgets.core.DateTimeMaskInput(attrs=None)¶
- class djgentelella.widgets.core.EmailInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.EmailMaskInput(attrs=None)¶
- class djgentelella.widgets.core.FileInput(attrs=None, extraskwargs=True)¶
- format_value(value)¶
File input never renders a value.
- value_from_datadict(data, files, name)¶
File widgets take data from FILES, not POST
- class djgentelella.widgets.core.FloatInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.HiddenInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.ImageRecordInput(attrs=None, extraskwargs=True)¶
You can set the preview size using data-width and data-height.
- class djgentelella.widgets.core.Input(attrs=None, extraskwargs=True)¶
Base class for all <input> widgets.
- class djgentelella.widgets.core.NumberInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.PasswordInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.PhoneNumberMaskInput(attrs=None)¶
- class djgentelella.widgets.core.PhoneNumberTwoDigitMaskInput(attrs=None)¶
- class djgentelella.widgets.core.SelectDateWidget(attrs=None)¶
- class djgentelella.widgets.core.SerialNumberMaskInput(attrs=None, format=None)¶
- class djgentelella.widgets.core.SplitDateTimeWidget(attrs=None)¶
- property media¶
Media for a multiwidget is the combination of all media of the subwidgets.
- class djgentelella.widgets.core.SplitHiddenDateTimeWidget(attrs=None)¶
- property media¶
Media for a multiwidget is the combination of all media of the subwidgets.
- class djgentelella.widgets.core.TaxIDMaskInput(attrs=None, format=None)¶
- class djgentelella.widgets.core.TextInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.TimeInput(attrs=None, format=None)¶
- class djgentelella.widgets.core.URLInput(attrs=None, extraskwargs=True)¶
- class djgentelella.widgets.core.VideoRecordInput(attrs=None, extraskwargs=True)¶
You can set the preview size using data-width and data-height.
Note
Size of video depends on camera default configuration.
- class djgentelella.widgets.core.VoiceDictation(attrs=None, extraskwargs=True, url=None, language=None)¶
Textarea with a continuous dictation button: captures audio in the browser (Web Audio + VAD) and, as the user speaks, posts each speech segment to a transcription endpoint that returns
{"text": "..."}; segments are inserted live.data-modeselects the strategy:segments(default, live),single(one request on stop) orhybrid(live segments then a whole-file rewrite on stop).Two kwargs, the rest through
attrs:urlis the transcription endpoint (voice_transcribeor a proxy) andlanguagesetsdata-language. Everything else is configured with plaindata-attributes, which is deliberate – the javascript reads them straight off the element, so a project can add its own without the widget growing a kwarg for each one, and a template can override one per field:VoiceDictation(url=reverse_lazy('voice_transcribe'), language='es', attrs={'data-mode': 'single'})
The ones the shipped engine understands:
- Data-mode:
dictation strategy –
segments(default, transcribes each speech segment live),single(one request when the user stops) orhybrid(live segments, then a whole-file rewrite on stop). An unknown value falls back tosegments.- Data-hotwords:
comma separated words to bias the recogniser towards.
- Data-initial-prompt:
free text giving the recogniser context.
Capture tuning, all numeric and all optional – the defaults live in the engine, and these are the seven keys
voiceVadConfigreads (gentelella/js/base/voiceprogressive.js):data-vad-silence-ms,data-vad-min-speech-ms,data-vad-max-segment-ms,data-rms-threshold,data-pool-size,data-max-session-msanddata-request-timeout-ms.hotwordsandinitial_promptonly reach a remote backend that was configured to accept them; the bundled Parakeet backend ignores both.
- class djgentelella.widgets.core.YesNoInput(attrs=None, shparent='.form-group')¶
Tree Widgets¶
Django Gentelella uses django-tree-queries for tree database representations.
TinyMCE Widget¶
- class djgentelella.widgets.tinymce.VoiceEditorTinymce(attrs=None, extraskwargs=True, url=None, language=None)¶
TinyMCE editor with a microphone button in its own toolbar for continuous voice dictation. Captures audio in the browser (Web Audio + VAD) and, as the user speaks, posts each speech segment to a transcription endpoint returning
{"text": "..."}; segments are inserted live viaeditor.insertContent.Configured exactly like
VoiceDictation– same engine, same attributes.urlandlanguageare kwargs;data-mode(segments|single|hybrid),data-hotwords,data-initial-promptand the seven capture-tuning keys go throughattrs, so a project can add its owndata-without the widget growing a kwarg per option:VoiceEditorTinymce(url=reverse_lazy('voice_transcribe'), attrs={'data-mode': 'hybrid'})
See
VoiceDictationfor what each attribute does.
Voice dictation ASR¶
Transcription endpoint (voice_transcribe) and the optional
in-process Parakeet-v3 backend. See Voice dictation widgets for usage and settings.
- class djgentelella.voice.views.VoiceTranscribeView(**kwargs)¶
Transcription endpoint for the voice dictation widgets, with two interchangeable backends selected by settings:
local— in-process Parakeet-v3 (needspip install "djgentelella[asr]"). Use when the load is light.remote— forward the audio to an external ASR HTTP API (needspip install "djgentelella[asr-remote]"andGENTELELLA_ASR_REMOTE_URL). Use when you need more power than the host can provide in-process. WhenGENTELELLA_ASR_REMOTE_TOKENis set, gentelella presents it as anAuthorization: Bearer <token>header (the external API should always require one).
Backend selection (
GENTELELLA_ASR_BACKEND): if unset, defaults toremotewhenGENTELELLA_ASR_REMOTE_URLis configured, otherwiselocal.Accepts a POST with the audio in the
filefield (plus optionallanguage,hotwordsandinitial_prompt;languagedrives the local backend and is forwarded to the remote one, the others are forwarded to remote backends that support them) and returns{"text": ...}.Uploads larger than
GENTELELLA_ASR_MAX_UPLOAD_BYTES(25 MB by default) are rejected with a 413: transcription is expensive in both backends (CPU in-process, billable API calls remotely) and each request holds a worker for up toGENTELELLA_ASR_TIMEOUTseconds.The view requires an authenticated user and enforces it itself, so it must not be wrapped in
login_required: that redirects, and the widget’sfetchwould follow the 302 and choke on the login page in.json().- get_backend()¶
Resolve the configured backend, failing loudly on a typo.
Both settings are commonly wired to
os.getenv, which yields''rather than leaving the setting out, so an empty value counts as unset.
Optional in-process Parakeet-v3 ASR for the voice dictation widgets.
Requires the asr extra:
pip install "djgentelella[asr]" # onnx-asr[cpu,hub] + av + numpy
Everything heavy (onnx_asr, av, numpy) is imported lazily so importing djgentelella stays free on installs without the extra. The model is loaded once per process (first request pays a ~670 MB download from Hugging Face and the warm-up cost); onnxruntime inference is thread-safe, so only the load is locked.
Configurable via settings:
GENTELELLA_ASR_MODEL(default"nemo-parakeet-tdt-0.6b-v3")GENTELELLA_ASR_QUANTIZATION(default"int8")GENTELELLA_ASR_LANGUAGE(default"es")GENTELELLA_ASR_PNC(defaultTrue) – punctuation & capitals
Note: Parakeet does not support hotwords/initial_prompt biasing; those
widget attrs are ignored by this backend.
- djgentelella.voice.asr.decode_to_f32_16k(source)¶
Decode any container/codec PyAV supports (webm/opus, ogg, wav, …) to a float32 mono 16 kHz waveform normalized to [-1, 1].
sourcemay be a file path or a file-like object withread().
- djgentelella.voice.asr.transcribe(source, language=None)¶
Decode
sourceand return the transcribed text (empty string if the audio has no decodable samples).languagedefaults toGENTELELLA_ASR_LANGUAGE. Whatever it resolves to is also passed to the model astarget_language, which is what stops Parakeet-v3 from translating to English instead of transcribing. Punctuation & capitals (GENTELELLA_ASR_PNC) are on by default.
Map Widgets¶
Leaflet based GPS point picker and dashboard map. See Map widgets for usage,
the use_maps flag and the API JSON contract.
- class djgentelella.widgets.maps.MapPointInput(attrs=None, extraskwargs=True, zoom=None, center=None, height=None, search=False, locate=True, based_fields=None, based_overwrite=False, tile_url=None, tile_attribution=None, geocoder_url=None)¶
Text input backed by a Leaflet map for picking a single GPS point.
The value is the plain string
"lat,lng"– no GeoDjango, GDAL or PostGIS involved, so it works on SQLite. The point can be set by clicking the map, dragging the marker, typing into the input, the “use my location” button or, when enabled, an address search.Unlike the read-only viewers in this library (
UrlTimeLineInput,MapBasedStoryMapInput) this widget submits a value, sorequiredanddisabledare deliberately left alone.- Parameters:
zoom – initial zoom level
center –
"lat,lng"or a(lat, lng)pair used when there is no value yetheight – CSS height for the map container, e.g.
"400px"search – show the address search box. Off by default – it geocodes through Nominatim, whose usage policy caps callers at 1 req/s and forbids heavy automated use.
locate – show the “use my location” button (hidden by the JS anyway outside a secure context, where the browser refuses to answer)
based_fields – CSS selectors of fields whose values are joined and geocoded to place the marker, e.g.
['#id_country', '#id_city']based_overwrite – let
based_fieldsmove a point the user already placed. Off by default.tile_url – tile layer template, defaults to OpenStreetMap
tile_attribution – attribution line for
tile_url. Most tile providers require one, so set it whenever you settile_url.geocoder_url – Nominatim compatible endpoint, for self-hosting
- djgentelella.fields.maps.DEFAULT_MAX_LENGTH = 63¶
Room for “-12.345678,-123.456789” plus a little slack.
- class djgentelella.fields.maps.GTPointField(*args, zoom=None, center=None, based_fields=None, search=False, map_attrs=None, **kwargs)¶
Model field storing a GPS point as the string
"lat,lng".A plain
CharField, so no GeoDjango, GDAL or PostGIS is needed and it works on SQLite. Useparse_point(obj.location)to get numbers back.The map options (
zoom,center,based_fields…) are forwarded toMapPointInputbyformfield().- deconstruct()¶
Re-emit the extra kwargs so migrations round-trip.
django-location-field omits this, which makes its model fields undeconstructible;
makemigrations --check(run bymake sdist) would catch that here.
- formfield(**kwargs)¶
Return a django.forms.Field instance for this field.
- class djgentelella.fields.maps.GTPointFormField(*, max_length=None, min_length=None, strip=True, empty_value='', **kwargs)¶
Form field for a
"lat,lng"point, rendered with a Leaflet map.- to_python(value)¶
Return a string.
- widget¶
alias of
MapPointInput
- djgentelella.fields.maps.LATLNG_ERRORS = {'invalid_format': "Enter a point as 'latitude,longitude'.", 'invalid_latitude': 'Latitude must be between -90 and 90.', 'invalid_longitude': 'Longitude must be between -180 and 180.', 'invalid_number': 'Latitude and longitude must be numbers.'}¶
One message per failure mode, keyed by the ValidationError code
validate_latlngraises.
- djgentelella.fields.maps.parse_point(value)¶
"lat,lng"->(lat, lng)floats, orNonewhen unparseable.Deliberately strict, so a malformed value is reported instead of being coerced into a plausible-looking point somewhere else on the planet.
- djgentelella.fields.maps.validate_latlng(value)¶
Validator with one message per failure mode, not a single generic one.
- class djgentelella.views.maps.BaseMapView(**kwargs)¶
Serves the point payload the
DJMapjavascript widget draws.DJMaphas no python widget class: a template includesgentelella/widgets/djmap.htmland points it at this view’s URL.Subclass it in
<app>/gtmaps.py, override the hooks and register it:@register_lookups(prefix="places", basename="placesmap") class PlacesMap(BaseMapView): def get_layers(self): return [{"name": "Offices", "points": [ {"lat": 9.93, "lng": -84.09, "popup": "<b>HQ</b>"}, ]}]
Then point the widget at
reverse_lazy('placesmap-list').Filters sent by the widget arrive in
self.request.query_params; narrow the queryset inside the hooks, the same contract the chart getters use.No
permission_classeshere on purpose: this is a base class meant to be combined, and the subclass – or the viewset it is mixed into – is what declares the authentication and permissions, the same wayBaseTimelineViewdoes. Whateverget_layers()returns is served to whoever can reach the URL, so a subclass over a non-public queryset has to say so.- get_center()¶
[lat, lng], or None to fit the map to the points instead.
- get_cluster()¶
Default clustering for layers that do not state their own.
- serializer¶
alias of
GTMapSerializer