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,
}
Related
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'
]
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.
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
I have something like the following:
class Destination(models.Model):
name = models.CharField
picture = models.ImageField
def __unicode__(self):
return u"%s" % self.name
class Vacation(models.Model):
destination = models.ForeignKey(Destination)
When creating the model in my Django Admin interface, I'd like my Destinations to be displayed as radio buttons with the Destination name and Destination picture.
I'm using a custom add_form template so displaying radio buttons with destination name is no problem, but including the picture is difficult.
I would like to leave __unicode__(self) as-is, I only need the picture returned with the object in this admin view. Also I don't want to inline the object.
Any advice on how to do this (including how to incorporate it into the template) would be great!
EDIT: This SO post comes very close to what I need, but I would like to access the individual choice data instead of parsing it from a modified label.
This is not an admin-specific answer, but I think it should work in admin if you can use a custom template for the form.
You could make a modified widget (probably as a subclass of an existing Django widget), that send extra fields from the model to a custom widget template.
You could also render the form manually in the template where it's displayed, and make an inclusion tag that fetches any extra information using the id of your destination object, which is passed as the value of the option.
For example:
your_template.html
{% load destinations %}
{% for opt in form.destination %}
{{ opt.tag }}
{% destination opt.data.value %}
{% endfor %}
destinations.py (in your_app/templatetags)
from django import template
from your_app.models import Destination
register = template.Library()
#register.inclusion_tag('your_app/destination-option.html')
def destination(id):
destination=Destination.objects.filter(id=int(id)).first()
return {'destination':destination}
destination-option.html
<!-- any formatting you prefer -->
{{destination.title}}
<img src="{{destination.picture.image_url}}">
I have the following form:
class ReviewForm(forms.ModelForm):
class Meta:
model = Review
widgets = {
'tipo' : forms.RadioSelect(),
}
But I want to use images as the values of my radio buttons, the image will vary according to the option, like this:
<input type="radio" id="id_tipo_0" value="UP" name="tipo" /><img src="/images/thumb_up.gif"/>
<input type="radio" id="id_tipo_1" value="DOWN" name="tipo" /><img src="/images/thumb_DOWN.gif"/>
I have no clues on how to achieve this.
There is a nice solution for this issue!
A ModelChoiceField has the method label_from_instance(self, obj). This method is called for every option in the ModelChoiceField.
You can overwrite ModelChoiceField.label_from_instance with:
def label_from_instance(obj):
"""
Shows an image with the label
"""
image = conditional_escape(obj.thumbnail_image.url)
title = conditional_escape(obj.title)
label = """<img src="%s" />%s""" % (image, title)
return mark_safe(label)
Note: you need to use mark_safe, otherwise the renderer will escape the img tag. Do apply the conditional_escape to the user input values (title and url).
If you want to use a regular ChoiceField you can just add HTML to the choices parameter and add mark_safe.
You can override RadioSelect (and RadioFieldRenderer) class.
OR! you can use jquery ( or something similar) to insert your img dynamically.
$(document).ready(function(){
$("#id_tipo_0").after('<img src="/images/thumb_up.gif"/>')
$("#id_tipo_1").after('<img src="/images/thumb_down.gif"/>')
});
If you want to use Django form rendering function, you'll have to use javascript to modifiy the DOM, and this will be a mess because the names of the option are rendered just after the input tag, not enclosed in any tag...
If your form does not have any other tags, go ahead, just write your input just as in your example, carefully using the Django names and values for the radio input, add a submit button, a CSRF token and that's all, you'll be able to validate your form in the view like if it was rendered via {{form.as_p}}