如何在django中为模型的每条记录创建一个带有复选框的表单

时间:2014-08-08 20:21:55

标签: django django-models django-forms

我有以下型号:

class Activity(models.Model):
    name = models.CharField(max_length=128)
    calories = models.IntegerField(default=0)
    type = models.IntegerField(choices=ACTIVITY_TYPES, default=0, blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add = True)
    updated_at = models.DateTimeField(auto_now = True)
    def __unicode__(self):
        return self.name

class CustomerActivity(models.Model):
    customer = models.ForeignKey(Customer)
    activity = models.ForeignKey(Activity)
    created_at = models.DateTimeField(auto_now_add = True)
    updated_at = models.DateTimeField(auto_now = True)
    def __unicode__(self):
        return self.activity.name

我想创建一个表单,允许用户将活动添加到他们自己的列表中,从而创建CustomerActivity条目。我认为最好的方法是创建一个带有每个Activity记录复选框的表单,然后在发布表单时保存CustomerActivity。

我该如何做到这一点?

1 个答案:

答案 0 :(得分:0)

这种形式的不同之处在于您事先不知道表单字段。基本上,您希望基于数据库数据生成表单。我曾经编码过同样的事情。诀窍在于Form对象将各个字段保存在名为fields的实例变量中,该变量是一个排序字典。您在dict中定义条目的顺序将是表单字段在表单中的显示顺序。

代码

#coding: utf-8

from django import forms
from models import Activity

class ActivitiesForm(forms.Form):
    def __init__(self, survey, *args, **kwargs):
        super(ActivitiesForm, self).__init__(*args, **kwargs)
        self.add_fields()

    def add_fields(self):
        # generate a queryset of the activities to show
        # could be sorted if a special order is needed
        activities = Activities.objects.all()
        if not activities:
            return

        for a in activities:
            # required false is important to allow the field NOT to be checked
            self.fields[a.id] = forms.BooleanField(label=a.name, required=False)

它做什么

创建表单时,它从数据库中提取所有活动,并为表单的每个活动添加BooleanField。此字段的字段名称将是活动的主键,复选框的标签是活动的名称。复选框在表单中的显示顺序将是主键的顺序。要更改它,只需根据需要对示例中的查询集活动进行排序。

当您现在评估表单时,您会得到一个数字列表,这些数字对应于所选活动的主键。从主键列表中,可以轻松地从数据库中检索相应的活动对象,并将其添加到客户对象上的m2m关系中。确保不使用标准的django add函数来向m2m关系添加内容,因为这对于m2m与额外字段的关系不起作用。有关如何完成的信息,请参阅django docs