How do I make a RadioSelect have a image as radio value? - django

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}}

Related

How to clear an image field in django forms?

So my views look like this:
class PostCreateView(CreateView):
model = Post
fields = ['title','content','image', 'status']
The image field currently looks like this:
Is there a way to have like a button to clear the image from the field? The only way to remove the image is to do it from django admin page.
your html file add a button with an id:
<button id="clear">Clear image </button>
Then in your html, add
{% load static %}
<script>
document.getElementById("clear").addEventListener("click", function () {
document.getElementById("image").value = "";
}, false);
</script>
Note that you need to use your chrome developor tool to find out what is the id of your file input field, in the above example, I used "image", but it most likely be different. You need to change get.ElementById("image") with the id of your file input field.

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,
}

Django form with label directly in the Field, but disappear on typing

I would like to achieve the same effect as google login page that the Label of the text field is shown in the field itself. When any characters is typed in the filed, the label automatically disappeared.
I know how to achieve similar effect with html + java script, like:
<input type="text" name="" id="" value="Email" class="gray" onclick="if(this.value=='Email')
{this.value='';this.className='black'}" onblur="if(this.value=='')
{this.value='Email';this.className='gray'}" />
But could django form does the same effect? I know I can specify initial in the CharField, but it won't disappear on typing.
forms.CharField(max_length=100, label=_("Email"), initial='xxx')
There is a html5 prop called placeholdertext. Here is a Blogpost about how to use it with django forms. Django HTML5 input placeholders
Excerpt:
class MyForm(Form):
name = forms.CharField(widget=forms.TextInput({ "placeholder": "Joe Recruiter" }))

Django MultiWidget format_output method and render method

Can anyone explain the format_output method and render method in django Multiwidget.
I have a Select box, a text field for email input and a checkbox. I have created a multiWidget but I want to have a add more feature, like if somebody clicks on the Add More button, javascript will replicate the set of fields that created by the multiWidget.
Also i want to render html like this :
<input type = "text" name=textbox_name[] />
how can I achieve this.
Thanks in advance.
Take a look at Django Formsets and related posts
dynamically add field to a form

Django Forms - change the render multiple select widget

In my model I have a manytomany field
mentors = models.ManyToManyField(MentorArea, verbose_name='Areas', blank=True)
In my form I want to render this as:
drop down box with list of all
MentorArea objects which has not
been associated with the object.
Next to that an add button which
will call a javascript function
which will add it to the object.
Then under that a ul list which has
each selected MentorArea object with
a x next to it which again calls a
javascript function which will
remove the MentorArea from the
object.
I know that to change how an field element is rendered you create a custom widget and override the render function and I have done that to create the add button.
class AreaWidget(widgets.Select):
def render(self, name, value, attrs=None, choices=()):
jquery = u'''
<input class="button def" type="button" value="Add" id="Add Area" />'''
output = super(AreaWidget, self).render(name, value, attrs, choices)
return output + mark_safe(jquery)
However I don't know how to list the currently selected ones underneath as a list. Can anyone help me? Also what is the best way to filter down the list so that it only shows MentorArea objects which have not been added? I currently have the field as
mentors = forms.ModelMultipleChoiceField(queryset=MentorArea.objects.all(), widget = AreaWidget, required=False)
but this shows all mentors no matter if they have been added or not.
Thanks
For me the functionality you described sounds a lot like what you can achieve with using the ModelAdmin' filter_horizontal and filter_vertical settings.
The widget they render lives in django.contrib.admin.widgets.FilteredSelectMultiple. You should have a look at its code!