I want to display a ManyToMany field into a widget/Html-form which the user can delete by X-ing items using jquery.
class user_profile:
links = ManyToManyField(...)
Then when I render the formset it would be something like:
<form>
<input type="checkbox" name="id" value="link_to_delete_item_using_ajax_call" />
....
....
</form>
Is there any existing? If not, how should I code it? ModelForm? Custom Form?
Thanks!
The best place for this is usually a custom Widget class. For example you could subclass CheckboxSelectMultiple and then use your custom widget in your form classes for relevant form fields.
The widget can automatically include the required JS/CSS by specifying it in the internal Media class
Related
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 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,
}
I am not quite sure about if i am taking the right approach to accomplish this. What i want is to (change the css for) / (use some jQuery methods on) the form elements rendered by the modelformset that have pre-filled data. For example i have the following modelformset.
EduFormSet = modelformset_factory(models.CandidateDegree,
form=forms.CandidateDegreeForm)
edu_formset = EduFormSet(prefix='candidate_degree',
queryset=models.CandidateDegree.objects\
.filter(candidate=can))
when i pass this formset to the template it renders forms for all the existing CandidateDegree objects with the pre-filled data and a blank form as well.
What i am trying to achieve is not to show the pre-filled forms but just the data for the objects that are already created and append an edit button to the element (using jQuery) which would then show the form. And at the end of the object list show the blank form generated by formset.
i am aware that i could pass all the CandidateDegree objects related to a Candidate as a seperate dictionary to show the information. but in that case how do i append the form to the formset so that the dynamically generated forms become the part of the formset and all the information is saved when a user clicks on a submit button.
what would be the best approach to achieve something like this ?
You don't have to show the complete form, you can loop over the formset like this:
{% for form in edu_formset %}
form.FIELDNAME#1.value
form.FIELDNAME#2.value
etc.
{% endfor %}
<!-- Manually render empty form for new entry -->
<div class='input'>
<label>Locality: </label> <input id="FIELDNAME#1" disabled=disabled value="">
<label>Country: </label> <input id="FIELDNAME#2" disabled=disabled value="">
etc.
</div>
So you're only showing the database values of all objects send to the template, not the form inputs.
Then indeed with minimal jquery (or plain javascript) you can show/hide the div.input
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
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}}