如何在Django中使模板标签自动勾选复选框

1 投票
2 回答
1520 浏览
提问于 2025-04-15 20:27

我正在使用一个ModelForm类来生成一堆复选框,这些复选框是为了处理一个多对多字段,但我遇到了一个问题:默认情况下,当我编辑一个对象时,系统会自动勾选合适的复选框,但我不知道怎么在我自己的自定义模板标签中获取这些信息。

这是我在模型中的代码:

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

这是我在视图中的代码:

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

这是我在模板中的代码:

{{ form.interests|alignboxes:"CheckOption" }}

这是我的模板标签代码:

@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\"><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)

问题是,我这样做只是为了在这些复选框周围包裹一些简单的标记,所以如果有人知道更简单的方法来实现这一点,我非常乐意听取建议。不过,我还是希望能找到一种方法来判断某个复选框是否应该被勾选。

2 个回答

3

在你的复选框的标签中,你可以根据某些条件来添加checked属性。比如说,你的复选框对象有一个属性checked,这个属性的值可能是“checked”或者是空字符串""。

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
)
0

原来我想要的值,也就是列表中被“选中”的元素,不是在field里,而是属于form对象的一部分。我重新调整了模板标签,变成了这样,正好满足我的需求:

@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

对于之后可能会遇到这个问题的人来说,注意上面提到的checked值是在boxes.form.initial[boxes.name]中找到的。

撰写回答