Django Form add class to div, input field and label - django

This is the html django form generated for an ImageField
<div id="div_id_image" class="form-group">
<label for="id_image" class=""> Image </label>
<div class=""> <input type="file" name="image" accept="image/*" class="clearablefileinput form-control-file" id="id_image">
</div>
Now, I can write custom html code to customize this field. But, my use-case is just to add 3 classes, one for the outer div, one for the label and one for the input field itself.
Is it possible to add these 3 classes in django form without writing any custom html code

It is possible. use "django-widget-tweaks" tools. It will give you full flexibility in your form.
check out the official documentation:
https://pypi.org/project/django-widget-tweaks/
If you want to add only class name from form.py
(you can try this but code is not tested)
from django import forms
class xyzform(forms.ModelForm):
x= forms.CharField(widget= forms.TextInput
(attrs={'class':'some_class',
'id':'some_id'}))
y= forms.CharField(widget= forms.TextInput
(attrs={'class':'some_class',
'id':'some_id'}))
class Meta:
model = xyzModal
fields = [
'x',
'y'
]

Related

Can django widget_tweaks render out input as textarea box?

I want to render out an input box as textarea with widget_tweaks in Django.
This is my code:
<div class="form-row">
<div class="form-group col-md-6">
<label>More information *</label>
{% render_field form.info class="form-control" %}
</div>
</div>
Everything is working fine, but it renders out as <input> tag. Is there any way to render it out as <textarea> without changing the models from CharField to TextField? I want to have a bigger box so there is more space to write the text. I know I can add a class that could change the size of the input box, but the textarea tag would be easier.
You can render CharField as textarea by specifying widget in your forms.py.
text = forms.CharField(widget=forms.Textarea)
or to set default width and height of textarea
text = forms.CharField(widget=forms.Textarea(attrs={"rows":3, "cols":10}))
There are two ways to incorporate this to your forms.py.
preferred way especially if you want to add widgets to multiple fields.
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields= ('text', 'field2')
widgets = {
'text': forms.Textarea(attrs={"rows":3, "cols":10})),
'field2': forms.RadioSelect(attrs= {
'class': 'choice_class'})
}
Note that although widget can add class, I think it is better to add css class or id using widget-tweaks at template level rather than widget.
another way in forms.py. This way works well when you want to add widgets to one or two fields.
class MyModelForm(forms.ModelForm):
text = forms.CharField(widget=forms.Textarea(attrs={"rows":3, "cols":10})
class Meta:
model = MyModel
fields = ('text', 'field2',)

Django - Modify Inlineformset Delete button

I do a custom UI/UX for an inlineformset.
By default the inlineformset widget has a delete button.
I wan to add and remove forms from inlineformset dynamic using javascript.
In some cases the delete is just a button instead of the checkbox, in other cases is in a modal window.
When a user click delete the form is removed from the page with javascript.
So, I try to do this without using the default widget, render fields in the template, but I don't know how to tell Django witch fields to remove and if is necessary to readjust the ids and names of the fields.
My solution for this problem was to just overwrite the template_name of CheckboxInput widget class:
widgets.CheckboxInput.template_name = 'widgets/delete.html'
I added that in my {app}/widgets.py that hosts my custom widgets. As I am using the same format accross my app, I think it's the only way to go.
{app}/templates/widgets/delete.html:
<div class="checkbox checkbox-styled">
<label>
<input name={{ widget.name }} type="checkbox" value="true" {% if widget.attrs.checked == True %}checked{% endif %}>
<span>Delete</span>
</label>
</div>
If it would not have been the inlineformset_factory then the best way was to create a new class extending BaseFormSet and to overwrite the widget in add_fields method like suggested in this answer.

Customising django ImageField markup in template

I have a form which allows you to upload an image, but I want to know if it is possible to customise the markup that Django generates.
In the model it is created as an ImageField:
logo = models.ImageField(blank=True, null=True)
In the template I am creating an 'upload' form field using
{{ form.logo }}
This is the markup that gets generated:
Currently: dog.jpg
<input id="logo-clear_id" name="logo-clear" type="checkbox">
<label for="logo-clear_id">Clear</label>
<br>Change: <input id="id_logo" name="logo" type="file">
I want to know if I can change that markup by drilling down further, so that I can for example nest the checkbox to clear the image within its label. I also would like to use my own markup to separate the option to clear the form field from the option to upload a new one. However, I can't find any documentation on how to do this. I've tried outputting
{{ logo.logo-clear }}
directly but this throws an error.
The solution was to create a custom version of the widget being used in my forms.py: https://docs.djangoproject.com/en/1.10/_modules/django/forms/widgets/#ClearableFileInput
from django.forms.widgets import ClearableFileInput
class CustomImageFieldWidget(ClearableFileInput):
template_with_clear = '<label for="%(clear_checkbox_id)s">%(clear)s %(clear_checkbox_label)s</label>'
class OrganisationProfileForm(OrganisationCreateForm):
class Meta(OrganisationCreateForm.Meta):
widgets = {
'logo': CustomImageFieldWidget,
}

achieve full customisation with django forms

I have a model with the following fields
class Entry(models.Model):
title = models.CharField(max_length=50)
comments = models.TextField()
start = models.DateField()
end = models.DateField()
remind = models.BooleanField()
and a modelform
class EntryForm(models.Model):
class Meta:
model = Entry
I want to render a form using bootstrap 3. I can render the form using the same kind of form e.g all fields horizontal or divide them by three in a row. How about more customization. Like
<label title>
<input title>
<label comments>
<input comments>
<label start> <label end>
<input start> <input end>
<label remind><input remind>
I guess this should be done manually. How can I know to which field of the form i am refering in the template. And by which field i mean is it title, is it comments? Is this correct (suppose the view has passed a form argument to the template) something like
<label for={{form.title.auto_id}}>Title</label>
{{form.title}}
is that correct? Now i can place what ever div's and arrange form fields as I like correct?Is that the right way?
How powerfull can a form of django be?
Here's a thought... Django has extensive, well-written documentation:
https://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template
Instead of guessing random things you could just read the docs.
Additionally there are a number of Django apps designed to simplify outputting form HTML in a Bootstrap style, such as:
https://github.com/dyve/django-bootstrap3 (recommended)
https://github.com/dyve/django-bootstrap-toolkit
https://github.com/tzangms/django-bootstrap-form

Django 1.5 Class Based Views with custom validation messages from the model

I'm writing a fairly simple bit of CRUD in my django application for project management. I've got the following set up (leaving out the various imports etc for brevity):
#models.py:
class Project(models.Model):
name = models.CharField('Name', max_length=250, error_messages={'required': 'Please enter a name for your project.'})
description = models.TextField()
#views.py
class ProjectUpdateView(UpdateView):
model = Project
#templates/projects/project_form.html
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" />
</form>
When I visit my update page, the form is displayed with my two fields (name and description). If I leave out the name then submitting the form brings back an error of
This field is required
rather than
Please enter a name for your project.
Can I get my custom error message as defined in the model to display instead of the generic "This field is required"?
Here's a Django ticket regarding the issue you're having: https://code.djangoproject.com/ticket/13693
Looks like it's been accepted but hasn't been fixed yet. Your best bet for now is to explicitly handle the validation in your form class.