103👍
Haven’t tested this, but based on reading Django’s code here and here I believe it should work:
class ThingForm(forms.ModelForm):
class Meta:
model = Thing
def __init__(self, *args, **kwargs):
super(ThingForm, self).__init__(*args, **kwargs)
self.fields['verb'].empty_label = None
EDIT: This is documented, though you wouldn’t necessarily know to look for ModelChoiceField if you’re working with an auto-generated ModelForm.
EDIT: As jlpp notes in his answer, this isn’t complete – you have to re-assign the choices to the widgets after changing the empty_label attribute. Since that’s a bit hacky, the other option that might be easier to understand is just overriding the entire ModelChoiceField:
class ThingForm(forms.ModelForm):
verb = ModelChoiceField(Verb.objects.all(), empty_label=None)
class Meta:
model = Thing
39👍
from the docs
The blank choice will not be included
if the model field has blank=False and
an explicit default value (the default
value will be initially selected
instead).
so set the default and you’re ok
- [Django]-Django TemplateDoesNotExist?
- [Django]-When should I use a custom Manager versus a custom QuerySet in Django?
- [Django]-Creating a JSON response using Django and Python
24👍
With Carl’s answer as a guide and after rooting around the Django source for a couple hours I think this is the complete solution:
-
To remove the empty option (extending Carl’s example):
class ThingForm(models.ModelForm): class Meta: model = Thing def __init__(self, *args, **kwargs): super(ThingForm, self).__init__(*args, **kwargs) self.fields['verb'].empty_label = None # following line needed to refresh widget copy of choice list self.fields['verb'].widget.choices = self.fields['verb'].choices
-
To customize the empty option label is essentially the same:
class ThingForm(models.ModelForm): class Meta: model = Thing def __init__(self, *args, **kwargs): super(ThingForm, self).__init__(*args, **kwargs) self.fields['verb'].empty_label = "Select a Verb" # following line needed to refresh widget copy of choice list self.fields['verb'].widget.choices = self.fields['verb'].choices
I think this approach applies to all scenarios where ModelChoiceFields are rendered as HTML but I’m not positive. I found that when these fields are initialized, their choices are passed to the Select widget (see django.forms.fields.ChoiceField._set_choices). Setting the empty_label after initialization does not refresh the Select widget’s list of choices. I’m not familiar enough with Django to know if this should be considered a bug.
- [Django]-Django model object with foreign key creation
- [Django]-How to merge consecutive database migrations in django 1.9+?
- [Django]-Check if OneToOneField is None in Django
22👍
You can use this on your model:
class MyModel(models.Model):
name = CharField('fieldname', max_length=10, default=None)
default=None is the answer 😀
NOTE: I tried this on Django 1.7
- [Django]-Django limit_choices_to for multiple fields with "or" condition
- [Django]-How to run a celery worker with Django app scalable by AWS Elastic Beanstalk?
- [Django]-How can I find the union of two Django querysets?
8👍
As for the django 1.4 all you need is to set the “default” value and “blank=False” on the choices field
class MyModel(models.Model):
CHOICES = (
(0, 'A'),
(1, 'B'),
)
choice_field = models.IntegerField(choices=CHOICES, blank=False, default=0)
- [Django]-How do I migrate a model out of one django app and into a new one?
- [Django]-How to limit the maximum value of a numeric field in a Django model?
- [Django]-How do I use an UpdateView to update a Django Model?
6👍
you can do this in admin:
formfield_overrides = {
models.ForeignKey: {'empty_label': None},
}
- [Django]-You are trying to add a non-nullable field 'new_field' to userprofile without a default
- [Django]-Django development server reload takes too long
- [Django]-Django – Login with Email
- [Django]-How to test "render to template" functions in django? (TDD)
- [Django]-Best way to integrate SqlAlchemy into a Django project
- [Django]-Django 2.0 path error ?: (2_0.W001) has a route that contains '(?P<', begins with a '^', or ends with a '$'
5👍
self.fields['xxx'].empty_value = None
would not work If you field type is TypedChoiceField
which do not have empty_label
property.
What we should do is to remove first choice:
1 . If you want to build a BaseForm
auto detect TypedChoiceField
class BaseForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(BaseForm, self).__init__(*args, **kwargs)
for field_name in self.fields:
field = self.fields.get(field_name)
if field and isinstance(field , forms.TypedChoiceField):
field.choices = field.choices[1:]
# code to process other Field
# ....
class AddClientForm(BaseForm):
pass
2.only a few form, you can use:
class AddClientForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(AddClientForm, self).__init__(*args, **kwargs)
self.fields['xxx'].choices = self.fields['xxx'].choices[1:]
- [Django]-Whats the difference between a OneToOne, ManyToMany, and a ForeignKey Field in Django?
- [Django]-Django vs. Model View Controller
- [Django]-Factory-boy create a list of SubFactory for a Factory
4👍
For a ForeignKey
field, setting the default
value to ''
on the model will remove the blank option.
verb = models.ForeignKey(Verb, on_delete=models.CASCADE, default='')
For other fields like CharField
you could set the default
to None
, but this does not work for ForeignKey
fields in Django 1.11.
- [Django]-Group by Foreign Key and show related items – Django
- [Django]-ImportError: No module named 'django.core.urlresolvers'
- [Django]-Specifying limit and offset in Django QuerySet wont work
3👍
I was messing around with this today and just came up with a coward hack nifty solution:
# Cowardly handle ModelChoiceField empty label
# we all hate that '-----' thing
class ModelChoiceField_init_hack(object):
@property
def empty_label(self):
return self._empty_label
@empty_label.setter
def empty_label(self, value):
self._empty_label = value
if value and value.startswith('-'):
self._empty_label = 'Select an option'
ModelChoiceField.__bases__ += (ModelChoiceField_init_hack,)
Now you can tweak the default ModelChoiceField
empty label to anything you’d like. 🙂
PS: No need for downvotes, non-harmful monkey patches are always handy.
- [Django]-Altering one query parameter in a url (Django)
- [Django]-How can I return HTTP status code 204 from a Django view?
- [Django]-How can I access environment variables directly in a Django template?
2👍
For the latest version of django
the first answer should be like this
class ThingForm(models.ModelForm):
class Meta:
model = Thing
def __init__(self, *args, **kwargs):
self.base_fields['cargo'].empty_label = None
super(ThingForm, self).__init__(*args, **kwargs)`
- [Django]-Using Cloudfront with Django S3Boto
- [Django]-Get path of virtual environment in pipenv
- [Django]-How to obtain a QuerySet of all rows, with specific fields for each one of them?
2👍
Since Django 1.7, you can customize the label for the blank value by adding a value to your choices list in your model field definition. From the documentation on configuring field choices:
Unless blank=False is set on the field along with a default then a label containing "———" will be rendered with the select box. To override this behavior, add a tuple to choices containing None; e.g. (None, ‘Your String For Display’). Alternatively, you can use an empty string instead of None where this makes sense – such as on a CharField.
I checked the documentation for different versions of Django and found that this was added in Django 1.7.
- [Django]-Only accept a certain file type in FileField, server-side
- [Django]-Why does django's prefetch_related() only work with all() and not filter()?
- [Django]-Django REST Framework – 405 METHOD NOT ALLOWED using SimpleRouter
1👍
I find SOLUTION!!
But not for ForeignKey 🙂
Maybe I can help you.
I looked in Django source code and discovered that in django.forms.extras.widgets.SelecteDateWidget() is a property called none_value that equals (0, ‘—–‘) so I did in my code this
class StudentForm(ModelForm):
class Meta:
this_year = int(datetime.datetime.today().strftime('%Y'))
birth_years = []
years = []
for year in range(this_year - 2, this_year + 3 ):
years.append(year)
for year in range(this_year - 60, this_year+2):
birth_years.append(year)
model = Student
exclude = ['user', 'fullname']
date_widget = SelectDateWidget(years=years)
date_widget.__setattr__('none_value', (0, 'THERE WAS THAT "-----" NO THERES THIS:-)'))
widgets = {
'beginning': date_widget,
'birth': SelectDateWidget(years=birth_years),
}
- [Django]-How to get Request.User in Django-Rest-Framework serializer?
- [Django]-Django.contrib.auth.logout in Django
- [Django]-How to send email via Django?
0👍
There are lots of great answers here, but I’m still not entirely satisfied with the implementations. I’m also a bit frustrated that select widgets from different sources (foreign keys, choices) yield different behaviours.
I have a design I’m working with where select fields always have a blank option, and if they’re required they will have a star next to them and the form will simply not validate if they’re left empty. That said, I can only properly override the empty_label for fields that are not TypedChoiceField
s.
Here’s what the result should look like. The first result is always the name of the field – in my case, the label
.
Here’s what I ended up doing. The following is an overridden __init__
method of my form:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for _, field in self.fields.items():
if hasattr(field, 'empty_label'):
field.empty_label = field.label
if isinstance(field, forms.TypedChoiceField):
field.choices = [('', field.label)] + [choice for choice in field.choices if choice[0]]
- [Django]-Import data from excel spreadsheet to django model
- [Django]-Django REST Framework: how to substitute null with empty string?
- [Django]-Can I access constants in settings.py from templates in Django?
0👍
This becomes more complicated when the choices are foreign keys and if you want to filter the choices based on some criteria. In such case if you set the empty_label
and then re-assign the choices (you can apply filtration here too) the empty label will be blank:
class ThingForm(models.ModelForm):
class Meta:
model = Thing
def __init__(self, *args, **kwargs):
super(ThingForm, self).__init__(*args, **kwargs)
self.fields['verb'].empty_label = None
self.fields['verb'].queryset=Verb.objects.all()
bbasically, the first line under init
can be applied for all of the fields in the form with a loop or inline loop:
def __init__(self,user, *args, **kwargs):
super(NewTicket, self).__init__(*args, **kwargs)
for f in self.fields:
self.fields[f].empty_label = None # or "Please Select" etc
- [Django]-How do you use the django-filter package with a list of parameters?
- [Django]-Django Sitemaps and "normal" views
- [Django]-How can I upgrade specific packages using pip and a requirements file?