How to get a template tag to auto-check a checkbox in Django
I'm using a ModelForm class to generate a bunch of checkboxes for a ManyToManyField but I've run into one problem: while the default behaviour automatically checks the appropriate boxes (when I'm editing an object), I can't figure out how to get that information in my own custom templatetag.
Here's what I've got in my model:
from myproject.interests.models import Interest
class Node(models.Model):
interests = models.ManyToManyField(Interest, blank=True, null=True)
class MyForm(ModelForm):
from django.forms import CheckboxSelectMultiple, ModelMultipleChoiceField
interests = ModelMultipleChoiceField(
widget=CheckboxSelectMultiple(),
queryset=Interest.objects.all(),
required=False
)
class Meta:
model = MyModel
And in my view:
from myproject.myapp.models import MyModel,MyForm
obj = MyModel.objects.get(pk=1)
f = MyForm(instance=obj)
return render_to_response(
"path/to/form.html", {
"form": f,
},
context_instance=RequestContext(request)
)
And in my template:
{{ form.interests|alignboxes:"CheckOption" }}
And here's my templatetag:
@register.filter
def alignboxes(boxes, cls):
"""
Details on how this works can be found here:
http://docs.djangoproject.com/en/1.1/howto/custom-template-tags/
"""
r = ""
i = 0
for box in boxes.field.choices.queryset:
r += "<label for=\"id_%s_%d\" class=\"%s\">开发者_如何学C;<input type=\"checkbox\" name=\"%s\" value=\"%s\" id=\"id_%s_%d\" /> %s</label>\n" % (
boxes.name,
i,
cls,
boxes.name,
box.id,
boxes.name,
i,
box.name
)
i = i + 1
return mark_safe(r)
The thing is, I'm only doing this so I can wrap some simpler markup around these boxes, so if someone knows how to make that happen in an easier way, I'm all ears. I'd be happy with knowing a way to access whether or not a box should be checked though.
In your input tag for the checkbox, you can just add the checked attribute based on some condition. Say your box object has property checked which value is either "checked" or empty string ""
r += "<label for=\"id_%s_%d\" class=\"%s\"><input type=\"checkbox\" name=\"%s\" value=\"%s\" id=\"id_%s_%d\" %s /> %s</label>\n" % (
boxes.name,
i,
cls,
boxes.name,
box.id,
boxes.name,
i,
box.checked,
box.name
)
Turns out the value I was looking for, the elements in the list that were "checked" isn't in the field
, but rather part of the form
object. I re-worked the template tag to look like this and it does exactly what I need:
@register.filter
def alignboxes(boxes, cls):
r = ""
i = 0
for box in boxes.field.choices.queryset:
checked = "checked=checked" if i in boxes.form.initial[boxes.name] else ""
r += "<label for=\"id_%s_%d\" class=\"%s\"><input type=\"checkbox\" name=\"%s\" value=\"%s\" id=\"id_%s_%d\" %s /> %s</label>\n" % (
boxes.name,
i,
cls,
boxes.name,
box.pk,
boxes.name,
i,
checked,
box.name
)
i = i + 1
return r
For those who might come after, note that the checked
value above was found in boxes.form.initial[boxes.name]
精彩评论