2012-04-19 156 views
3

我试图更新某些ModelForm字段,这些字段不固定。 (我只有一个由视图autopopulated tutorDjango - ModelForm动态字段更新

型号:

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

如何在视图中做到这一点?


编辑

我已经给了例子,但它并不限于这些例子,我需要更新不是预定义的领域,我需要能够更新任何字段(S)

+0

当你说'更新'时,你是什么意思?你渲染所有表单域还是只更新那些域? – okm 2012-04-19 12:42:02

+0

我只渲染那些更新。 (更新我的意思是改变这个值) – 2012-04-19 12:45:04

+0

你可以举一个例子,比如使用场景吗?仍然不是很确定你的目的。 – okm 2012-04-19 12:47:44

回答

8

我不得不这样做之前类似的东西,虽然它不完美,但它是非常有效的。它涉及在运行时动态创建一个类型,并使用该类型。对于一些文档,你可以看到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! 
+0

我喜欢这个。什么不漂亮? – 2012-04-19 14:31:12

+0

我应该说,这不直观。在考虑我对动态表的实现时,我写了'不漂亮'的评论。这实际上看起来相当优雅。 – 2012-04-19 14:38:18

+0

为什么不直接生成并返回表单?用'type()'构造对于在'attrs'中有动态字段的动态模型非常有用,在你的代码中'attrs'只有'Meta'类。无论如何。 – okm 2012-04-19 17:48:52

1

把你的表单字段可为空,并用“干净”的方法,你可以添加逻辑来场前:

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'] 

如果你想CH ange值,对return语句使用不同的值。

这是您可能需要验证的内容。

如果你愿意,你可以复制得到您的视图和更新值字典实例化表单

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) 
    [...] 

希望它能帮助之前。

+0

不完全回应我的问题,但您的验证规则很有趣,我会用它们:) – 2012-04-19 10:05:02

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

如果我有一个有10个字段的模型,并且每个模块都是可独立更新的,那么您的意思是我必须为每个模块都这样做? – 2012-04-19 09:32:09

+0

在这种情况下,你应该有哪一个规则需要更新?给你的10个字段命名一个像field_1,field_2这样的约定,然后你应该使用一个循环来完成这一步。 – vutran 2012-04-19 09:36:39

+0

或使用kwargs,您将可以使用setattr轻松转换值。但我认为,复制你的post/get查询字典并在视图中修改它可能是一种很好的方式,你可以在字段上进行遍历并计算你想要的内容,然后通过表单验证你的修改。 – christophe31 2012-04-19 09:48:06

0

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

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

有了这个,你将有两种不同的形式,取决于相同的模型,具有不同的默认字段。

通过巧妙的网址和视图设计,您将能够使用上述想法为同一模型中的多个表单提供服务。