Django - CheckboxSelectMultiple without "------" choice - django

How can I remove "------" from rendered choices?
I use in my model form:
widgets = {
'event_form': forms.CheckboxSelectMultiple(),
}
In model I have IntegerField with choices:
EVENT_FORM_CHOICES = (
(1, _(u'aaaa')),
(2, _(u'bbbb')),
(3, _(cccc')),
(4, _(u'dddd')),
(5, _(eeee'))
)
rendered choices contain --------- as first possible choice. How I can get rid of it?
EDIT:
The only working way i figured out is (in init method):
tmp_choices = self.fields['event_form'].choices
del tmp_choices[0]
self.fields['event_form'].choices = tmp_choices
but it's not very elegant way :)

Update
a similar example maybe useful:
country = ModelChoiceField(reference_class = Country, choices= country_choices,
required=True, empty_label=None, widget=forms.Select)
If you want a solution client side instead:
<script>
$("#selectBox option[value='-----']").remove();
</script>

Django is including the blank choice because the field doesn't have a default value.
If you set a default value in your model, then Django will not include the blank choice.
class MyModel(models.Model):
event_form = models.PositiveSmallIntegerField(choices=EVENT_FORM_CHOICES, default=1)
If you don't want to set a default value in your model, then you can explicitly declare the field and choices in the model form, or change the choices in the model form's __init__ method.

I ran into a similar problem but fixed it this way. First, download and install https://pypi.python.org/pypi/django-multiselectfield. If you don't know how to install, look here: django-multiselectfield can't install. Then, in models.py:
from multiselectfield import MultiSelectField
CHOICES_FOR_ITEM_WITH_CHOICES = (
("choice 1", "choice 1"),
("choice 2", "choice 2"),
("choice 3", "choice 3"),
)
class MyModel(models.Model):
item_with_choices = MultiSelectField(max_length=MAX_LENGTH, null=True, blank=True)
In admin.py:
from .forms import MyModelForm
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
list_display = ('item_with_choices',)
list_filter = ('item_with_choices',)
search_fields = ('item_with_choices',)
admin.site.register(MyModel, MyModelAdmin)
In forms.py (you can name this whatever you like):
from .models import MyModel
class MyModelForm(ModelForm):
class Meta:
model = MyModel
fields = (
'item_with_choices',
)
def clean(self):
# do something that validates your data
return self.cleaned_data
This builds off the answer here: Django Model MultipleChoice

Related

Django Admin Panel Choices from Database

I have a model that has a IntegerField and in the admin. I want to add choices to the widget as "University" field. There is no problem if I add the universities in list as uniList.
But I do not know how can add these universities from UniversityList Class. I want to add new universities to UniversityList on admin panel and then I want to choose these added universities in Mainland2 admin page.
In this case I received error message as
in get raise self.model.MultipleObjectsReturned(mainpage.models.MultipleObjectsReturned: get() returned more than one UniversityList -- it returned 5!
Thank you for in advance...
from django.db import models
from django import forms
from django_countries.fields import CountryField
from django.core.exceptions import ValidationError
class UniversityList(models.Model):
name = models.CharField(max_length=50)
class Mainland2(models.Model):
unilist = [
(0, "---"),
(1, "Uni 1"),
(2,"Uni 2"),
(3,"Uni 3"),
]
graduatedList=[
(0, "Diğer"),
(1, "Lise"),
(2, "Lise (Öğrenci)"),
(3, "Ön Lisans"),
(4, "Ön Lisans (Öğrenci)"),
(5, "Lisans"),
(6, "Lisans (Öğrenci)"),
(7, "Yüksek Lisans"),
(8, "Yüksek Lisans (Öğrenci)"),
(9, "Doktora"),
(10, "Doktora (Öğrenci)")
]
def validate_digit_length(idName):
if not (idName.isdigit() and len(idName) == 11):
raise ValidationError('%(idName)s en az 11 karakter olmalıdır', params={'idName': idName}, )
name = models.CharField(max_length=20, verbose_name="Ad")
midName = models.CharField(max_length=20, verbose_name="Orta Ad", null=False, blank=True)
surName = models.CharField(max_length=20, verbose_name="Soy Ad")
university = models.IntegerField(choices=UniversityList.objects.get(),default=0, verbose_name="Son Mezun Olunan Üniversite")
graduated = models.IntegerField(choices=graduatedList, default=0, verbose_name="Tahsil Durumu")
def __str__(self):
return f"{self.name},{self.surName}"
class Meta:
db_table = "mainland2"
verbose_name_plural = "Ar-Ge Personeller"
Doing objects.get() like that will try to get 1 object from the database, but you've got 5 by the sounds of it.
Something like objects.first() would work, but also it's a bad idea to perform that operation on the database in the model like that. You should override forms to perform the database operation in the creation of the form.
So, keep the field on the model simple;
university = models.IntegerField(default=0, verbose_name="Son Mezun Olunan Üniversite")
Then setup the choices in any forms which use the model. An example of this would look like;
class Mainland2Form(forms.ModelForm):
""" Mainland2 form """
class Meta:
""" Setup the form """
model = Mainland2
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
unis = UniversityList.objects.values_list(
'id', 'name'
)
# Make sure we've got an empty choice to avoid people not using the field taking the first choice
uni_choices = \
[(None, '')] + [(u[0], u[1]) for u in list(unis)]
self.fields['university'].choices = uni_choices
You can then override the admin form for your admin class. Check out these docs;
https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
What you probably want though, given you're doing this in admin, is just a ForeignKey relationship. Django will then handle the choices for you.
And when it comes to FK relationships in admin, you should consider the additional overhead of having to select all the related objects in order to generate the select box.
If the related model has a lot of objects, you can reduce this database query by using raw_id_fields on your model admin.
For example;
class Mainland2Admin(admin.ModelAdmin):
raw_id_fields = ("university",)
https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.raw_id_fields

Django model form how to output select Yes/No from Booleanfield

I'm trying to have a yes/no selection on a booleanfield. The default widget is checkboxinput. However if I override the default widget with Select I get a:
NameError: Select is not defined
I think this may be because I need to setup Yes/No to correlate to the boolean values in the booleanfield, but not sure how this should be done?
Model:
class User(models.Model):
online_account = models.BooleanField()
Form:
class AccountForm(forms.ModelForm):
class Meta:
model = User
fields = ('online_account')
labels = {
'online_account': 'Do you have an online account',
}
widgets = {'online_account': Select()}
I found (and tested with Django 1.9.6) this gist. It should do the trick:
from django import forms
class Form(forms.Form):
field = forms.TypedChoiceField(coerce=lambda x: x =='True',
choices=((False, 'No'), (True, 'Yes')))
Just set the choices in the template's boolean field
from django.utils.translation import gettext_lazy as _
CHOICES_BOOLEANO_SIM_NAO = (
(True, _('Sim')),
(False, _('Não'))
)
class modelo(models.Model):
"""Model definition for LoteModalidadeEvento."""
# TODO: Define fields here
e_bool_field= models.BooleanField(verbose_name=_('Este é um campo booleano'), **choices**=CHOICES_BOOLEANO_SIM_NAO)

Specify choices in model and RadioButton in ModelForm renders not selected value "------"

My goal is to be able to use get_FOO_display(), and so as far as I understand I will have to have choices specified in the model field. At the same time I am wanting to render the form using a ModelForm as a RadioButton.
The problem I am having is that the default value of "------" that would be used in a dropdown select is showing up as one of my RadioButton options.
models.py
class Medication(models.Model):
YESNO_CHOICES = [(0, 'No'), (1, 'Yes')]
Allergies = models.BigIntegerField(verbose_name='Allergies:', choices=YESNO_CHOICES)
forms.py
I have tried just specifying a RadioButton widget in the ModelForm.
class mfMedication(ModelForm):
class Meta:
model = Medication
widgets = {
'Allergies': RadioSelect(),
}
and also specifying the RadioButton with the CHOICES.
class mfMedication(ModelForm):
class Meta:
model = Medication
widgets = {
'Allergies': RadioSelect(choices=Medication.YESNO_CHOICES),
}
In both cases I get three radiobuttons:
"": -------
0 : No
1 : Yes
The only way I do not get the "-------" is to remove choices=YESNO_CHOICES from my model field, but this stops get_FOO_display() from working.
Any approach that you have used to get this working would be greatly appreciated.
Thanks. JD.
If you want to prevent displaying of ------- choice, you should specify empty_label=None in your form field.
Also, I recomend you to use BooleanField for model and TypedChoiceField for form:
models.py:
class Medication(models.Model):
Allergies = models.BooleanField('Allergies:')
forms.py:
class MedicationForm(forms.ModelForm):
YESNO_CHOICES = ((0, 'No'), (1, 'Yes'))
Allergies = forms.TypedChoiceField(
choices=YESNO_CHOICES, widget=forms.RadioSelect, coerce=int
)
Using the BigIntegerField, you can also set the default=0 or whatever choice you would like it to be.

Django - pre-selected radio button from BooleanField

I have been able to get the BooleanField from my main Feature class to be rendered as a radiobutton for its form, but when viewed, the form doesn't have the corresponding value preselected. How do I get it to select the appropriate one, given a boolean value? Thanks
models.py:
class Feature(models.Model):
for_biz = models.BooleanField()
class FeatureForm(ModelForm):
choices = ( (1,'Business'), (0, 'Customers') )
for_biz = forms.TypedChoiceField(
coerce=lambda x: bool(int(x)),
choices=choices,
widget=forms.RadioSelect,
)
class Meta:
model = Feature
fields = (
'for_biz',
)
views.py:
def edit_feature(request, f_id):
f = get_object_or_404(Feature, id=f_id)
form = FeatureForm(instance=f)
....
Make it a PositiveSmallIntegerField with choices. BooleanField doesn't really buy you anything, and as you already saw it only gives you more trouble to deal with.

Django: Admin: changing the widget of the field in Admin

I have a model with a boolean value like that:
class TagCat(models.Model):
by_admin = models.BooleanField(default=True)
This appears as a checkbox in admin.
How could I use this as a radio button in admin?
Also, how do I make it be always with a certain selected value in admin?
Also, I want the default value to be the opposite, when a non-admin user adds a TagCat. This field should be hidden from him.
Can someone tell me how to do this? Django documentation doesn't seem to go in such details.
UPDATE 1: Code that gets me done with 1) (don't forget tot pass CHOICES to the BooleanField in the model)
from main.models import TagCat
from django.contrib import admin
from django import forms
class MyTagCatAdminForm(forms.ModelForm):
class Meta:
model = TagCat
widgets = {
'by_admin': forms.RadioSelect
}
fields = '__all__' # required for Django 3.x
class TagCatAdmin(admin.ModelAdmin):
form = MyTagCatAdminForm
admin.site.register(TagCat, TagCatAdmin)
The radio buttons appear ugly and displaced, but at least, they work
I solved with following info in MyModel.py:
BYADMIN_CHOICES = (
(1, "Yes"),
(0, "No"),
)
class TagCat(models.Model):
by_admin = models.BooleanField(choices=BYADMIN_CHOICES,default=1)
There is another way to do this that is, IMO much easier if you want every field of the same type to have the same widget. This is done by specifying a formfield_overrides to the ModelAdmin. For example:
from django.forms.widgets import Textarea
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.TextField: {'widget': Textarea},
}
More in the docs: https://docs.djangoproject.com/en/1.4/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides
Here is a more dynamic extension of mgPePe's response:
class MyAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MyAdminForm, self).__init__(*args, **kwargs)
self.fields['by_admin'].label = 'My new label'
self.fields['by_admin'].widget = forms.RadioSelect()
class Meta:
model = TagCat
class MyAdmin(admin.ModelAdmin):
fields = ['name', 'by_admin']
form = MyAdminForm
This way you get full control over the fields.