使用django ModelForm在创建模型实例之前修改数据

时间:2014-03-01 17:19:58

标签: django django-models django-forms

型号:

class Foo(model.Model):
    a = model.CharField()

class Bar(model.Model):
    b = model.ForeignKey(Foo)
    ... more fields here

我正在使用ModelForm来创建Bar对象。我希望用户能够输入Bar.b的字符串,然后检查数据库中是否存在Foo对象。如果是这样,那么将它用于Bar.b,否则创建一个Foo并使用它。

class BarForm(forms.ModelForm):
    b = forms.CharField()
    class Meta:
        model = Bar
        fields = ['b', ...]

Bar的'create'函数包含如下内容:

try:
    foo = Foo.objects.get(a=input_string)
except Foo.DoesNotExist:
    foo = Foo(a=input_string)

bar = Bar(b=foo, ...)

我该如何实施?

1 个答案:

答案 0 :(得分:1)

如果我理解正确,你想把Foo实例附加到Bar, 基于用户对字段a的输入,并自动创建Foo实例 如果还不存在。

使用这些模型:

class Foo(model.Model):
    a = model.CharField()

class Bar(model.Model):
    b = model.ForeignKey(Foo)
    ... more fields here

在你的ModelForm中你可以这样做:

class BarForm(forms.ModelForm):
    class Meta:
        model = Bar
        fields = [other fields from the Bar model, ...]

    foo_a = forms.CharField(...)

    foo_instance = None  # for clarity/documentation only

    def clean_foo_a(self):
        value = self.cleaned_data['foo_a']
        self.foo_instance = Foo.objects.get_or_create(a=value)
        return value

    def save(self, *args, **kwargs):
        """
        Attach Foo to the newly created Bar instance.
        The code below takes into account the standard "commit" kwarg for ModelForm's
        """
        commit = kwargs.pop('commit', True)
        bar_instance = super(BarForm, self).save(commit=False, *args, **kwargs)
        bar_instance.b = self.foo_instance
        if commit:
            bar_instance.save()
        return bar_instance

我们的想法是添加另一个字段 - foo_a - 我们将用它来查找/创建Foo实例。

其他可能性包括为您执行此操作的自定义小部件,自定义表单字段等, 但这一切都取决于你在应用程序中使用这种模式的频率。