使用ModelForm优雅地设置OneToOneField中使用的Model的单个属性

时间:2013-07-11 13:15:45

标签: django django-forms

我可以使用heightMyLittleModel)更新MyModelForm OneToOneField(MyLittleModel)属性,如下所示:

models.py

class MyLittleModel(models.Model):
    height = models.IntegerField()
    has_color = models.NullBooleanField(null=True, blank=True)


class MyModel(models.Model):
    my_little_model = models.OneToOneField(MyLittleModel)
    age = models.IntegerField()
    is_male = models.BooleanField(default=False)

forms.py

class MyModelForm(forms.ModelForm):
    height = forms.IntegerField(max_length=30)

    class Meta:
        model = MyModel
        fields = ("height", 
          "age")

views.py

class MyUpdateView(UpdateView):
    form_class = MyModelForm
    model = MyModel
    template_name = 'my_template.html'

    def form_valid(self, form):
        my_little_model = MyLittleModel.objects.create(form.cleaned_data["height"])
        form.instance.my_little_model = my_little_model
        form.instance.save()
        return super(MyUpdateView, self).form_valid(form)

    def get_success_url(self):
        return reverse("my_list_view")

urls.py

urlpatterns = patterns('',
    url(regex=r'^update/(?P<pk>\d+)/$', view=MyUpdateView.as_view(), name="my_update_view"),
)

我认为这不是一个好的编码风格,因为这会迫使你修改ModelForm和View中的代码,最好只在一个位置发生这种情况。

那么可以像我一样修改我的观看代码,将值设置为my_little_model.height吗?

注意:我不喜欢这个问题的标题,如果有人建议将其重命名为更易读的内容,请告诉我。

1 个答案:

答案 0 :(得分:1)

我会通过覆盖你的MyModelForm的保存方法来实现这一点,如下所示:

class MyModelForm(forms.ModelForm):
    height = forms.CharField(max_length=30)

    class Meta:
        model = MyModel
        fields = ("height",
          "age")

    def save(self, *args, **kwargs):
        my_little_model = MyLittleModel.objects.create(height=self.cleaned_data["height"])
        self.instance.my_little_model = my_little_model
        self.instance.save()
        return super(MyModelForm2, self).save(*args, **kwargs)

然后您的观点变为:

class MyUpdateView(UpdateView):
    template_name = "my_template.html"
    form_class = MyModelForm
    model = MyModel

    def get_success_url(self):
        return reverse("my_list_view")

这样,您更新模型信息的所有逻辑都存在于表单中 - 如果您想要更改正在更新的内容,您可以在一个地方完成所有操作。