pre-selected checkbox in django with django forms - django

Am trying to display a pre-selected checkbox in Django :
option = forms.BooleanField(required=False, initial=True)
but the checkbox shows up un-checked. Am using django 1.3 beta. Am I missing something here ?

import django
from django import forms
class MyForm(forms.Form):
option = forms.BooleanField(required=False, initial=True)
>>>print MyForm()
<tr><th><label for="id_option">Option:</label></th><td><input checked="checked" type="checkbox" name="option" id="id_option" /></td></tr>
>>> django.VERSION
(1, 3, 0, 'beta', 1)
>>>
As you can see the checked="checked" is properly set.
Are you sure you are not modifying something with onload javascript ?

Set the attributes field:
options = forms.MultipleChoiceField(label='some label', choices=(('happy','Happy'),('sad','Sad')),
widget=forms.CheckboxSelectMultiple(attrs={'checked' : 'checked'}))

Try:
option = forms.BooleanField(
widget=forms.CheckboxInput(attrs={'checked': True})
)

Related

Replacement for the default ManyToMany Widget of Forms

I know who to replace the ManyToMany Widget in the django admin interface:
class SomeModelAdmin(admin.ModelAdmin):
filter_horizontal = ('users',)
But how to replace the default widget in all views?
I guess this could be implemented without changing one line in my code or in django.
It would be great if I could the something like the Author part (two boxes for a ManyToMany input) in this picture with a widget:
I can use ctrl + click, but my users can't. They want an easier way.
Is there a way to replace all select-multiple widgets without many changes in my code?
You can use a base class which ovride formfield_for_manytomany
from django.contrib.admin import widgets
class ManyToManyAdmin(admin.ModelAdmin):
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
kwargs['widget']= widgets.FilteredSelectMultiple(
db_field.verbose_name,
db_field.name in self.filter_vertical
)
return super(admin.ModelAdmin, self).formfield_for_manytomany(
db_field, request=request, **kwargs)
class SomeModelAdmin(ManyToManyAdmin):
pass
If I do not understand your question, please clarify in the comments.
The Django Form Widgets Documentation offers several pre-fab widgets that you can use to specify how a field in your form is rendered.
Without modifying the code in my views, I can simply add a widget keyword arg to the appropriate form fields.
forms.py (v1)
class TestForm(forms.Form):
CHOICES = (
(1, "choice1"),
(2, "choice2"),
(3, "choice3"),
)
field = forms.ChoiceField(choices=CHOICES)
This renders as a dropdown select:
<select id="id_field" name="field">
<option value="1">choice1</option>
<option value="2">choice2</option>
<option value="3">choice3</option>
</select>
Now adding the widget keyword arg to my field:
forms.py (v2)
field = forms.ChoiceField(choices=CHOICES, widget=forms.CheckboxSelectMultiple)
This renders as a list of checkboxes:
<ul id="id_field">
<li>
<label for="id_field_0"><input id="id_field_0" name="field" type="checkbox" value="1" /> choice1</label>
</li>
<li>
<label for="id_field_1"><input id="id_field_1" name="field" type="checkbox" value="2" /> choice2</label>
</li>
<li>
<label for="id_field_2"><input id="id_field_2" name="field" type="checkbox" value="3" /> choice3</label>
</li>
</ul>
Edit
It is also possible to add widgets that are used by Django Admin. See Django multi-select widget? for more information about this. Simply import the appropriate widget:
from django.contrib.admin.widgets import FilteredSelectMultiple
and use that instead. Note that in this particular case you will also need to include the form's media to get the desired effect.
You need to replace default widgets in django forms.
This works for me:
from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
# replace MultipleChoise in Forms
forms.MultipleChoiceField.widget = FilteredSelectMultiple("verbose name", is_stacked=False)
# replace MultipleChoise in ModelForms
forms.ModelMultipleChoiceField.widget = FilteredSelectMultiple("verbose name", is_stacked=False)
Add code above to file forms_setup.py in your main project
Then in settings.py import file forms_setup.py:
from .forms_setup import *

Populate a PasswordField in wtforms

Is it possible to populate a password field in wtforms in flask?
I've tried this:
capform = RECAPTCHA_Form()
capform.username.data = username
capform.password.data = password
The form is defined like:
class RECAPTCHA_Form(Form):
username = TextField('username', validators=[DataRequired()])
password = PasswordField('password', validators=[DataRequired()])
remember_me = BooleanField('Remember me.')
recaptcha = RecaptchaField()
The template looks like this:
<form method="POST" action="">
{{ form.hidden_tag() }}
{{ form.username(size=20) }}
{{ form.password(size=20) }}
{% for error in form.recaptcha.errors %}
<p>{{ error }}</p>
{% endfor %}
{{ form.recaptcha }}
<input type="submit" value="Go">
</form>
I have tried to change the PasswordField to a TextField, and then it works.
Is there some special limitation to populating PasswordFields in wtforms?
Update: After looking through the WTForms docs I found an even better solution. There is a widget arg.
from wtforms import StringField
from wtforms.widgets import PasswordInput
class MyForm(Form):
# ...
password = StringField('Password', widget=PasswordInput(hide_value=False))
As yuji-tomita-tomita pointed out, the PasswordInput class (source) has an hide_value argument, however the constructor of PasswordField (source) does not forward it to the PasswordInput. Here is a PasswordField class that initializes PasswordInput with hide_value=False:
from wtforms import widgets
from wtforms.fields.core import StringField
class PasswordField(StringField):
"""
Original source: https://github.com/wtforms/wtforms/blob/2.0.2/wtforms/fields/simple.py#L35-L42
A StringField, except renders an ``<input type="password">``.
Also, whatever value is accepted by this field is not rendered back
to the browser like normal fields.
"""
widget = widgets.PasswordInput(hide_value=False)
Something I've found with Flask, and Flask apps in general, is that the source is the documentation. Indeed, it looks like by default you cannot populate the field. You can pass an argument hide_value to prevent this behavior.
This is a good call, since if you can populate the field, you have access to the raw password... which could be dangerous.
class PasswordInput(Input):
"""
Render a password input.
For security purposes, this field will not reproduce the value on a form
submit by default. To have the value filled in, set `hide_value` to
`False`.
"""
input_type = 'password'
def __init__(self, hide_value=True):
self.hide_value = hide_value
def __call__(self, field, **kwargs):
if self.hide_value:
kwargs['value'] = ''
return super(
I believe there is an easier way to access the data of the password field, without usinghide_value. In your view, simply add in the request data as an argument to the form's constructor:
from flask import request
capform = RECAPTCHA_Form(request.form)
capform.username.data = username
capform.password.data = password
This should make the password input available for validation, and to be used in testing if desired.

Django: Unable to add UPPERCASE attribute name in HTML input element

I'm trying to use a javascript library in django that requires some attributes for HTML elements in camelCase. For example, I've a model with a CharField field like this:
expires = models.DateField("Expiration Date", db_index = False, blank = True, null = True, editable = True, help_text = "Something")
My ModelForm has the following line in the init method:
self.fields['expires'].widget.attrs['SomeAttribute'] = "SomeValue"
and after the render_to_response the outputed HTML is like this:
<input id="id_expires" type="text" name="expires" someattribute="SomeValue">
instead of:
<input id="id_expires" type="text" name="expires" SomeAttribute="SomeValue">
Am I missing something?
As Issac points out at the top, what you've should be correct. The Django internals responsible for rendering the above in django.forms.widgets
return mark_safe(u'<input%s />' % flatatt(final_attrs))
should give you the correct attr you're looking for. I did get to replicate your problem when I inspected the HTML rendered in Firebug. It seems that Firebug lowercases the attribute name but when I did a view source code, it did show as SomeAttribute versus someattribute in Firebug (if this is indeed what you're doing :))
I couldn't find anything in the django forms codebase that suggests that it's anything that's django's fault. How are you rendering the form? Please see my shell session for my details.
>>> from django import forms
>>> class F(forms.Form):
... a = forms.CharField()
...
>>> f = F()
>>> f.as_p()
u'<p><label for="id_a">A:</label> <input type="text" name="a" id="id_a" /></p>'
>>> f.fields['a'].widget.attrs
{}
>>> f.fields['a'].widget.attrs['dERP'] = 'ddf'
>>> f.as_p()
u'<p><label for="id_a">A:</label> <input id="id_a" type="text" name="a" dERP="ddf" /></p>'
>>>

django : set default value for formset_factory form element

Model:
class AssociatedFileCourse(models.Model)
file_original = models.FileField(upload_to = 'assets/associated_files')
session = models.ForeignKey(Session)
title = models.CharField(max_length=500)
Form:
class AddAssociatedFilesForm(ModelForm):
class Meta:
model = AssociatedFileCourse
If I had to create a single form from above defination and set some initial value, It could have done using initial parameter like
form = AddAssociatedFilesForm(initial={'session': Session.objects.get(pk=id)})
how to set the initial form values when creating a formset_factory forms like:
AddAssociatedFilesFormSet = formset_factory(AddAssociatedFilesForm)
form = AddAssociatedFilesFormSet()
You want to use modelformset_factory, which is tailored to create and act on formsets of Model instances.
from django.forms.models import modelformset_factory
# create the formset by specifying the Model and Form to use
AddAssociatedFilesFormSet = modelformset_factory(AssociatedFileCourse, form=AddAssociatedFilesForm)
# Because you aren't doing anything special with your custom form,
# you don't even need to define your own Form class
AddAssociatedFilesFormSet = modelformset_factory(AssociatedFileCourse)
By default a Model formset will display a form for every Model instance - i.e. Model.objects.all(). In addition you'll have blank forms allowing you to create new Model instances. The number of blank forms is subject to the max_num and extra kwargs passed to modelformset_factory().
If you want initial data you can specify it with the initial kwarg when generating the formset. Note, the initial data needs to be inside a list.
formset = AddAssociatedFilesFormSet(queryset=AssociatedFileCourse.objects.none(),
initial=[{'session': Session.objects.get(pk=id)}])
That should look like you want it. However, you cannot (in current Django versions at least) create a Model formset with existing Model instances and initial data for the extra forms. That's why the objects.none() queryset is there. Set it to objects.all() or remove the queryset kwarg and - if you have instances - the extra forms will not have the initial data.
Further reading on Model formsets with initial data - see this post.
You would do it in the same way, except using a list of values in the dictionary rather than just a value.
From Django docs on formsets:
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
>>> formset = ArticleFormSet(initial=[
... {'title': u'Django is now open source',
... 'pub_date': datetime.date.today()},
... ])
>>> for form in formset:
... print form.as_table()
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title" /></td></tr>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date" /></td></tr>
<tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title" /></td></tr>
<tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date" /></td></tr>
<tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
<tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>

Django - birthdate fildset as form widget

If I have in forms.py:
birthdate = forms.DateTimeField()
and html:
<fieldset class='birthday-picker'>
<select class='birth-year' name='birth[year]'></select>
<select class='birth-month' name='birth[month]'></select>
<select class='birth-day' name='birth[day]'></select>
<input type='hidden' name='birthdate' />
</fieldset>
Do I need create a new widget or there is an answer for this? If there is no answer i will be grateful for every advice how to do this
There is a built in widget that already does that.
from django.forms import extras
class SomeForm(forms.ModelForm):
birthdate = forms.DateField(widget=extras.SelectDateWidget)
If the html doesn't have to be exactly like this, you might get away easier with a pure javascript solution like the jquery datepicker or use djangos own admin datewidget.
for version >= 1.9
from django import forms
class Some_Form(forms.Form):
birthday = forms.DateField(
widget=forms.SelectDateWidget
)
or
use jquery-ui
$(document).ready(function(){
$('.datepicker').datepicker({ dateFormat: 'yy-mm-dd' });
})