How to add empty_label in forms.ModelForm? - django

For instance, I have this code. How can I add the empty_label to the field Select.
class NameForm(forms.ModelForm):
class Meta:
model = Model
fields = ['choice',]
widgets = {
'choice': forms.Select(attrs={'class': 'class'}, ??empty_label='lorem'??),
}
models.py
class Book(models.Model):
choice = models.ForeignKey('Another Model', on_delete=models.PROTECT, null=True)

This is a parameter of the form field, not the widget. If you do not want to override the rest of the form field, you specify this in the constructor of the form:
class NameForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['choice'].empty_label = 'lorem'
class Meta:
model = Model
fields = ['choice',]
widgets = {
'choice': forms.Select(attrs={'class': 'class'}),
}

Related

How to delete label of a form in Django

How can I delete label of form in Django. I have something like this.
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['user_image']
widgets = {
'user_image': forms.FileInput(attrs={'class': 'image-upload', 'label': ''}),
}
image-upload class does not include label. I have a auto-generated label and is written 'user-image'
You can remove it via init:
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['user_image']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['user_image'].label = ''

Django form.save() error

my model:
class Event(models.Model):
title = models.CharField(max_length=255)
start = models.DateTimeField()
end = models.DateTimeField()
theme = models.ForeignKey(Theme)
class Theme(models.Model):
name = models.CharField(max_length=100)
color = models.CharField(max_length=50)
text_color = models.CharField(max_length=50)
my form:
class EventForm(ModelForm):
class Meta:
model = Event
fields = ['title', 'start', 'end']
theme = forms.ModelChoiceField(
queryset=Theme.objects.filter(public=True),
empty_label='None'
)
my view:
#login_required
def index(request):
if request.method == 'POST':
form = EventForm(request.POST)
if form.is_valid():
form.save()
Now If I fill in the values in the form star, end, title and select a theme from a list that django creates for me I get an error when I try to run the form.save() method.
IntegrityError: null value in column "theme_id" violates not-null constraint
But when I look into form.cleaned_data I can see that in theme is an instance of my Theme model available.
you cannot save Event without Theme object, so you need something like
form = EventForm(request.POST)
if form.is_valid():
# get your Theme object 'your_theme_object'
event = form.save(commit=False)
event.theme = your_theme_object
event.save()
I should have commented but I don't have enough point.
I think better way to achieve this thing is:
class EventForm(ModelForm):
class Meta:
model = Event
fields = ['title', 'start', 'end', 'theme']
As 'theme' is foreign key to Event Model, it'll appear as drop down on your template.
As here you want to filter theme objects, you can achieve it by overriding init :
class EventForm(ModelForm):
def __init__(self, *args, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)
self.fields['theme'].queryset = self.fields['theme'].queryset.filter(public=True)
class Meta:
model = Event
fields = ['title', 'start', 'end', 'theme']

conditionally change widget type in django form

I have the following simple form:
class ContactEmailForm(forms.ModelForm):
subject = forms.ChoiceField(choices=SUBJECT_TYPES)
class Meta:
model = ContactEmail
fields = ('name', 'email', 'subject', 'message',)
I want to conditionally change the subject field between a choice field and text input field.
How can I do this?
This could be accomplished by overriding the __init__ function within your ContactEmailForm class.
class ContactEmailForm(forms.ModelForm):
subject = forms.ChoiceField(choices=SUBJECT_TYPES)
def __init__(self, *args, **kwargs):
super(ContactEmailForm, self).__init__(*args, **kwargs)
if YOURCONDITION:
self.fields['subject'] = forms.CharField()
class Meta:
model = ContactEmail
fields = ('name', 'email', 'subject', 'message',)

How do I add a help_text to a ModelForm?

I know how to add a 'class' or other widget attribute to an automatically built ModelForm:
class ExampleSettingForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ExampleSettingForm, self).__init__(*args, **kwargs)
self.fields['example_field'].widget.attrs['class'] = 'css_class'
class Meta:
model = Example
How do I insert a help_text= into the example_field Field?
As of Django 1.6: You can edit it within the Meta class. Try:
class ExampleSettingForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ExampleSettingForm, self).__init__(*args, **kwargs)
self.fields['example_field'].widget.attrs['class'] = 'css_class'
class Meta:
model = Example
help_texts = {
'example_field': ('Here is some help'),
}
Docs on this are at https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-fields. See release notes at http://django.readthedocs.org/en/latest/releases/1.6.html . You can set your own label, help_text and error_messages.
This is what I did in Django 1.9:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ('__all__')
help_texts = {
"my_field": "This is case sensitive..."
}

Dynamic Form fields in `__init__` in Django admin

I want to be able to add fields to django admin form at runtime. My model and form:
#admin.py
class SitesForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(SitesForm, self).__init__(*args, **kwargs)
self.fields['mynewfield'] = forms.CharField()
class SitesAdmin(admin.ModelAdmin):
form = SitesForm
admin.site.register(Sites,SitesAdmin)
#model.py
class Sites(models.Model):
url = models.URLField(u'URL')
is_active = models.BooleanField(default=True, blank=True)
is_new = models.BooleanField(default=False, blank=True)
group = models.ForeignKey('SitesGroup')
config = models.TextField(blank=True)
Field mynewfield isn't displayed in form. Why?
You shouldn't be adding a new field to your form in that way, you can just do it as you would any other field and the form will contain both the Model's original fields and your new fields:
class SitesForm(forms.ModelForm):
mynewfield = forms.CharField(max_length=255, blank=True)
class Meta:
model = Sites
class SitesAdmin(admin.ModelAdmin):
form = SitesForm
admin.site.register(Sites, SitesAdmin)
Edit: Sorry, should have read what you had written a little better. If you want a dynamic field like that, then you need to do the following and it will do exactly what you want:
class SitesForm(forms.ModelForm):
class Meta:
model = Sites
def __init__(self, *args, **kwargs):
self.base_fields['mynewfield'] = forms.CharField(max_length=255, blank=True)
super(SitesForm, self).__init__(*args, **kwargs)
class SitesAdmin(admin.ModelAdmin):
form = SitesForm
admin.site.register(Sites, SitesAdmin)
It's the base_fields that gets composed by the metaclass that holds the fields that the form will use.
Solution:
class AdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(AdminForm, self).__init__(*args, **kwargs)
self.fields.insert(1, 'myfield', forms.CharField())
class MyAdmin(admin.ModelAdmin):
form = AdminForm
def get_fieldsets(self, request, obj=None):
return (
(None, {
'fields': (..., 'myfield',),
}),
)