Django - ModelForm动态字段更新

时间:2012-04-19 07:59:16

标签: python django django-forms

我正在尝试更新ModelForm的某些字段,这些字段不是固定的。 (我只有tutor由视图自动填充)

型号:

class Session(models.Model):
  tutor = models.ForeignKey(User)
  start_time = models.DateTimeField()
  end_time = models.DateTimeField()
  status = models.CharField(max_length=1)

形式:

class SessionForm(forms.ModelForm):
  class Meta:
    model = Session
    exclude = ['tutor']

对于特定会话,有时我只需更新end_time,有时只需更新start_time& end_time

我如何在视图中执行此操作?


修改

我已举出示例但不限于这些示例,我需要更新的字段未预定义,我需要能够更新任何字段

4 个答案:

答案 0 :(得分:9)

我以前必须做类似的事情,虽然它不是很漂亮,但它非常有效。它涉及在运行时动态创建类型,并使用该类型。对于某些文档,您可以看到DynamicModels for django.

我们在这里......你的要求。

  • 您希望能够使用表单
  • 更新模型
  • 您希望有选择地指定在运行时更新哪些字段

所以,有些代码:

def create_form(model, field_names):
    # the inner class is the only useful bit of your ModelForm
    class Meta:
        pass
    setattr(Meta, 'model', model)
    setattr(Meta, 'include', field_names)
    attrs = {'Meta': Meta}

    name = 'DynamicForm'
    baseclasses = (forms.ModelForm,)
    form = type('DynamicForm', baseclasses, attrs)
    return form

def my_awesome_view(request):
    fields = ['start_time', 'end_time']
    form = create_form(Session, fields)
    # work with your form!

答案 1 :(得分:1)

将表单字段设置为可空,使用“干净”方法可以将字段添加到字段ex:

class SessionForm(forms.ModelForm):
    def clean_end_date(self):
        cd = self.cleaned_data
        if (cd["start_date"] and cd["end_date"]) and cd["end_date"] < cd["start_date"]:
            raise forms.ValidationError("WTF?!")
        if not (cd["start_date"] or cd["end_date"]):
            raise forms.ValidationError("need one date")
        return cd['end_date']

如果要更改值,请对return语句使用不同的值。

这是验证所需的内容。

如果需要,您可以在视图中复制GET字典并在实例化表单之前更新值

def my_view(request):
    r_data = request.GET.copy()
    r_data.merge(request.POST)

    data = dict([(key, my_function(key, value)) for key, value in r_data.iteritems() if key in MyForm.fields])
    form = MyForm(data=data)
    [...]
希望它有所帮助。

答案 2 :(得分:0)

您可以像这样调用表单的构造函数:

class SessionForm(forms.ModelForm):
    class Meta:
        model = Session
        exclude = ['tutor', 'start_time']

    def __init__(self, your_extra_args, *args, **kwargs):
        super(SessionForm, self).__init__(*args, **kwargs)
        if need_end_time_start_time(your_extra_args):
            self.fields['start_time'] = forms.DateTimeField()     

要使用此类,您必须将参数“your_extra_args”传递给表单:

session_form = SessionForm('foo')

答案 3 :(得分:0)

您的问题表明您有一个使用相同模型的要求,但根据您的需要,您的ModelForm中隐藏了不同的字段。

如果我理解你的问题,那么你需要创建两个不同的基于ModelForm的类,这两个类在Meta类中都有相同的模型值。排除并包含您需要的字段。所以现在你有了不同的ModelForm类,你可以在你的视图逻辑中调用它们。

通过这种方式,您将拥有两种不同的形式,这些形式依赖于相同的模型,具有不同的默认字段。

通过巧妙的网址和视图设计,您将能够使用上述理念来提供来自同一模型的多种表单。