Django forms: How to add class to field_content? - django

When I render a form, it generates something like this for each Field:
<div class="field_content">
<label>...</label>
<div class="field">...</class>
</div>
I would like to be able to uniquely identify each Field in my stylesheet. Is there a way to add another class to the outer div (in addition to field_content), or an outer div (parent to field_content)?

If it's enough to set the class of the field you can specify it as an attribute of your widget:
name = forms.CharField(widget=forms.TextInput(attrs={'class':'special'}))
If you need more control it's probably best to render your form manually or if you don't mind relying on an external app there are even more flexible solutions:
In django-floppyforms you could use form layouts and in django-crispy-forms you could use layout objects and to achieve what you want.

Related

Hiding ModelMultipleChoiceField on template for custom input

I want the user to select a number of elements belonging to a certain model. I don't want to use the default 'ctrl+click' input of django forms, but create a table of checkboxes myself.
For that reason I hide the ModelMultipleChoiceField by defining the widget:
field = forms.ModelMultipleChoiceField(..., widget=forms.MultipleHiddenInput())
Then I add the form element into the template as follows:
<form method="POST" class="locklist-form" id="locklist-form">{% csrf_token %}
{{ form.field }}
</form>
At this step, I expect the select-option elements to be added to HTML page (as hidden), so that I can reach to element options and modify them with javascript. However, it doesn't add anything to the HTML page.
I use this approach with other type of form fieds. For a TextField HTML page have a hidden element as shown:
Why doesn't it work with ModelMultipleChoiceField? How can I modify the choices of this field with Javascript?
Edit:
MultipleHiddenInput renders only if with initial data is a similar question. But applying it doesn't lead to the expected solution. In this question, it is expected to render the following as hidden:
But following the MultipleHiddenInput renders only if with initial data, when I modify the form constructor as:
form = MyForm(initial={'field':MyModel.objects.all()})
Rendered element is as follows:
It maybe useful, but not exactly the expected one. I need to mark a few options as selected, among a list of objects.
I have done it using Javascript, instead of depending on Django's capabilities. I add the form with ModelMultipleChoiceField directly to the template (not hidden). Then I run a Javascript script, when the page is loaded:
var field = document.getElementById('id_field');
selecter.setAttribute('class', 'hidden');
CSS definition of hidden class is as follows:
.hidden{
display: none;
}
This gets me to the desired situation. ModelMultipleChoiceField is rendered hidden as follows:
At this point, I can modify certain items through Javascript:
document.getElementById('id_field').options[index].selected = boolValue;

Django - wrap each form element in a <div>

The Django forms API has methods Form.as_p(), Form.as_table() and Form.as_ul(), which wrap form elements in <p>, <tr> and <li> tags respectively.
Is there any way to wrap form elements in a <div>, like in the canonical Bootstrap forms example?
Why not render form fields manually?
With this ability you have absolute freedom of how you can manipulate the "look" of a form. You can define CSS classes, ids etc.

How to make a dynamic menu in base template using django

I'm about to start a new project and I think this time django is the way to go. I've been reading the documentation for the past two weeks and it looks promissing.
Ok, the thing is that I could not find anything about (in C# MVC called) Partial Rendering. For example if I want a dynamic menu where the menu-items comes from the database, then I would expect that the base template (or master page) renders the menu on each request (the partial renderer invokes another action or renders a template with some session data). So, the menu comes for free as long as my template inherits from this base template.
Honestly, I have no clue on how to achieve this.
What I would like is some code in the base template that uses data that is not contained in the child template. I don't want to include an extra variable (maybe 'menu_list_items') every time I call render_to_response('child_content.html',context). Is this possible?
Thanks!
You could either use a context processor, or a custom template tag to provide this functionality.
A context_processor is a simple function which can add objects to every RequestContext. A custom template tag can have its own template snippet and context which could render the menu for you.
For the template reusing: you should just create a base template for the generic layout, and use detailed templates for the individual pages. This is already covered in detail by the Django documentation.
What I tend to do for those generic parts (say for example, a menu highlighting the current part of the site the use is on), is to create my own render_to_response functions, akin to the following:
from django.shortcuts import render_to_response as django_render_to_response
def render_to_response(template, params, context_instance):
return django_render_to_response(template,
AppendStandardParams(request, params),
context_instance)
The ApplyStandardParams method then configures the menu based on the current path:
def AppendStandardParams(request, params):
if request.META['PATH_INFO'].startswith('/customer'):
params['category'] = 'customer'
params['title'] = 'Customer overview'
# and so on for all different parts
These category and title tags in this example are some values used to highlight the menu, configure titles, and so on. For example:
<!-- Customer menu entry: change class if this is the current category. -->
<li{% if category == "customer" %} class="selected"{% endif %}>Customers</li>
Finally, to use it in a view, instead of the normal render_to_response import, I just do something like from lib.views import *, which makes my custom version available in the view. This way the syntax of all code in the views stays the same, but I don't have to customize the menu every time I create a new view or app.

django - post form on select

I made a simple django form, with a list of choices (in radio buttons):
class MyForm(forms.Form):
choices=forms.ChoiceField( widget=forms.RadioSelect(), choices=[(k,k) for k in ['one','two','three']],label="choose one")
I would like the form to submit automatically when a user selects one of the options. In straightforward HTML I would've done it as
<select name='myselect' onChange="FORM_NAME.submit();">
....
</select>
But I do not know how to integrate this into the form class without writing a template. Specifically, I would need to know FORM_NAME so I can call FORM_NAME.submit() in the above snippet.
Can it be done without using a template?
I think you do not need to know the form name. This should work as well:
<select name='myselect' onChange="this.form.submit();">
A quick solution to integrate this into your form would involve adding a attribute to your widget.
widget=forms.RadioSelect(attrs={'onchange': 'this.form.submit();'})
Now one could argue if this isn't better separated from your form definition (separating definition, style and behaviour), but that should do it.

Customizing RadioSelect

Hello I have a form with ChoiceField whose widget is set to RadioSelect
Now to override default html output one needs to subclass RadioFieldRenderer like this:
class SimpleRadioFieldRenderer(forms.widgets.RadioFieldRenderer):
def render(self):
"""Outputs widget without <ul> or <li> tags."""
return mark_safe(u'\n'.join([u'%s'
% force_unicode(w.tag()) for w in self]))
All is good now except I'd like to be able to render 1 radio button at a time from template.
Something like this:
{{ form.myfield.0 }}}
Or perhaps hanging it onto widget itself:
{{ form.myfield.field.widget.0 }}
What bugs me is that RadioFieldRenderer already implements __get_item__ to get just one RadioInput. The problem is that the renderer does not contain data, neither does the widget. And I'd really hate to mess with Field and BoundField.
I need this to inject html before/after each radiobutton and I'd like it to be done in the template. From the code it would be easy.
Any ideas are welcome.
I think this post in django-users may provide a way to do it (with an accessor function in the form class):
http://groups.google.com/group/django-users/msg/b60410692c7c60e2