A more simple version of [https://djangosnippets.org/snippets/1688/](https://djangosnippets.org/snippets/1688/), inheriting from `SelectDateWidget`, overriding only the necessarily.
**Usage example:**
**In models.py:**
from django.db import models
from django.utils.translation import gettext_lazy as _
class MyModel(models.Model):
start = models.DateField(
_("Start date"),
)
end = models.DateField(
_("End date"),
)
class Meta:
verbose_name = _("My model")
**In forms.py:**
from django import forms
from .models import MyModel
from .widgets import MonthYearWidget
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
exclude = []
widgets = {
"start": MonthYearWidget(),
"end": MonthYearWidget(last_day=True),
}
**kwargs:**
- *last_day :* if set to `True`, returns the last day of the month in the generated date.
A minimally invasive Select widget that looks and acts like a disabled select input, but still submits with the form. It works by rendering the form as disabled, and supplements it's output with a hidden input field with the same name and value.
Tested in Django 3.0, probably works in Django 1.11+
You need jQuery and Bootstrap 2 and bootstrap-dropdown.js. Apart from that, this should be a perfect drop-in replacement for the normal select widget. A jQuery event callback maintains a hidden input field from the user's selection. Upon loading the page, the hidden input field is set.
The SelectWidgetBootstrap also contains a <noscript> tag containing the normal forms.Select widget.
Example usage:
class MyForm(forms.Form):
group = forms.ModelChoiceField(models.Group.objects.all(), widget=SelectWidgetBootstrap(),
empty_label=_(u'(no group selected)'))
A Select widget that allows choices to be disabled. Specify `disabled_choices` to indicate which choices should be present in the list, but disabled.
A possible use case for this is a form that displays data that can be edited by privileged user's but only viewed by others.
Because select_related() only works on ForeignKeys that are not null or blank, when you are customizing the admin, even if you set "list_select_related=True" you can still end up with way too many querys in the Admin changelist. By adding this code to your model you can decrease the queries dramatically.
I found I needed this when I was working with Django apps with a lot of legacy data and I couldn't set the ForeignKey null=False.
HTML allows an option in a <select> to be disabled. In other words it will appear in the list of choices but won't be selectable. This is done by adding a 'disabled' attribute to the <option> tag, for example:
`<option value="" disabled="disabled">Disabled option</option>`
This code subclasses the regular Django Select widget, overriding the render_option method to allow disabling options.
Example of usage:
class FruitForm(forms.Form):
choices = (('apples', 'Apples'),
('oranges', 'Oranges'),
('bananas', {'label': 'Bananas',
'disabled': True}), # Yes, we have no bananas
('grobblefruit', 'Grobblefruit'))
fruit = forms.ChoiceField(choices=choices, widget=SelectWithDisabled())
This widget will produce a select box with the range of dates that you input.
**Usage:**
`widget=SelectDateWidget('2010-12-15', '2010-12-20')`
**Output:**
`<select>
<option value="2010-12-15">Wed January 01, 2010</option>
<option value="2010-12-16">Thu January 02, 2010</option>
<option value="2010-12-17">Fri January 03, 2010</option>
<option value="2010-12-18">Sat January 04, 2010</option>
<option value="2010-12-19">Sun January 05, 2010</option>
<option value="2010-12-20">Mon January 06, 2010</option>
</select>`
This widget can be imported in your forms.py file and used like so:
formfield = forms.ModelChoiceField(widget=SelectDropdownWidget, queryset=Model.objects.all())
The javascript is provided by [filament group's Scott and his jQueryUI Selectmenu](http://www.filamentgroup.com/lab/jquery_ui_selectmenu_an_aria_accessible_plugin_for_styling_a_html_select/). In addition to the javascript you will need [jQuery (the latest release is fine) and jQuery UI](http://jqueryui.com/). The convenient thing is that this widget will style to match whichever jQuery UI you've 'rolled' or selected, making it highly customizable!
Hopefully this helps others who wanted a nice widget with jQuery and were sad to find there were no nice default options, enjoy! :)
This is an example of how you change a ChoiceField select widget into a hidden field if the right GET variable is passed. In this example code it would change the select widget into something like the following if something like "?d=3" was passed.
`<p><label for="id_designation">Designation</label>Designation Option<input type="hidden" name="designation" value="3" id="id_designation" /></p>`
If you need a simple select list (picklist) containing all site categories (or some other taxonomic group) and don't want to depend on Javascript, here's how to build a simple category navigator in Django, using HttpResponseRedirect.
This code will allow you to use chained select boxes in the django automatic admin area. For example, you may have a product, then a category and subcategory. You'd like to create a product, and then choose a category, and then have a chained select box be filled with the appropriate subcategories.
This widget will render a chained select menu powered by JavaScript to make it easier to identify foreign keys. This widget includes danjak's form decorator (http://www.djangosnippets.org/snippets/59/), and Xin Yang's chained select javascript functions (http://www.yxscripts.com/).
I developed this to be used with an IT inventory system. See screenshot here: http://bayimg.com/cAjAGAabN
The models are laid out that location -> area -> room. But the __str__ of area and room did not include unique fields, so the built-in single select box that django uses for ForeignKey's did not work for me.
A few notes:
1: I will not be maintaining this, I am only putting it out here in case it helps others.
2: The chained select menus will only be available to the first form on the page. Reason being: the template names the form, not the django backend. So, I had to reference the form in javascript as document.forms[0].
3: Due to the javascript processing, the chain select menu will not show current values other than the default specified in the javascript. Thus, form_for_instance and a dict of values passed to form_for_model will not pre-set the chained select.
4: The rendered selects are put into a vertical table. No other layout is supported.
5: The select field names for upper-leveled options are "chain_to_[destination_field_name]__[current_selects_model_name].
6: The select name for the destination option is the name that django sends internally, which is usually the field name. The value of each option in the select is the primary key associated with that object.
7: I tried to get this built in to the native form_for_model helper function for use with the default admin site, but failed miserably.
How to get it working (quick version):
1: Define your models
2: From your view, import the form_decorator and ChainSelectWidget (I put them in CustomWidgets.py and made sure it was in the path).
3: Build arguments for the form_decorator eg:
widget_overwrite=dict(field=ChainSelectWidget(order=[(top, 'order_field'), (next, 'order_field'), (field, 'order_field)]
4: Send arguments to form_decorator eg:
callback = form_decorator(widgets=widget_overwrite)
5: Build modified form eg:
mod_formclass = form_for_model(field, formfield_callback=callback)
6: Instance the modified form eg:
instanced_form = mod_formclass()
7: Send instanced form to the templating engine
8: From the template, import the chainedselects function file (replace [] with <>) eg:
[head][script language="javascript" src="path/to/chainedselects.js"][/script]
9: Display the form object as you normally would.
Observation: depends on jQuery to works!
This widget works like other multiple select widgets, but it shows a drop down field for each choice user does, and aways let a blank choice at the end where the user can choose a new, etc.
Example using it:
class MyForm(forms.ModelForm):
categories = forms.Field(widget=DropDownMultiple)
def __init__(self, *args, **kwargs):
self.base_fields['categories'].widget.choices = Category.objects.values_list('id', 'name')
super(MyForm, self).__init__(*args, **kwargs)
Usage:
from yourapp.fields import CheckBoxManyToMany
from django.db import models
class Weekday(models.Model):
name = models.CharField()
def __unicode__(self):
return self.name
class EventWithWeekday(models.Model):
weekdays = CheckBoxManyToMany(Weekday)