在Django模型表单中使用Model属性

时间:2014-02-27 07:41:30

标签: python django forms

我试图使用模型属性,比如模型表单中的字段,但到目前为止还没有任何运气。结果是表单只呈现模型字段,而不是我定义的属性。知道如何让表单识别添加到模型中的属性吗?我希望将latitude属性添加为表单中的另一个字段。

Models.py:

class Plot(models.Model):
        plot_id = models.AutoField(primary_key=True)
        plot_number = models.IntegerField(validators=[MinValueValidator(1)], null=False, unique=True)
        geometry = models.PointField(srid=2163, null=True, blank=True) 
        objects = models.GeoManager()

        @property
        def latitude(self):
            self.geometry.transform(4326)
            return self.geometry.y

        @latitude.setter
        def latitude(self, latitude):
            self.geometry.y = latitude

Forms.py:

class InventoryPlotForm(ModelForm):
    class Meta:
        model = ForestInventoryPlot
        exclude = {"geometry"}

3 个答案:

答案 0 :(得分:3)

您的属性不是Field实例,因此ModelForm无法自动为其生成表单字段。您需要在latitude上明确定义InventoryPlotForm字段,并使用表单的__init__save方法管理其检索和更新。或者,您可以实施自己的Widget课程,并告诉InventoryPlotForm将其用于geometry字段:

class InventoryPlotForm(ModelForm):
    class Meta(object):
        widgets = {
            'geometry': MyGeometryWidget,
        }
        ...
    ...

答案 1 :(得分:1)

ModelForm只会自动生成Django字段。

  • 您需要在ModelForm中定义您的字段
  • 可能隐藏几何字段
  • 编写自定义ModelForm Save方法并单独保存模型字段和模型属性。
  • 修改视图以设置ModelForm的初始值

例如:

class InventoryPlotForm(ModelForm):
    latitude = forms.CharField(max_length=52)           # Something like this

    def save(self, commit=True):
        model_instance = super(InventoryPlotForm, self).save(commit=False)
        result = super(InventoryPlotForm, self).save(commit=True)
        model_instance.latitude = self.cleaned_data['latitude']
        model_instance.save()
        return result

    class Meta:
        model = ForestInventoryPlot
        widgets = {'geometry': HiddenInput()}
在您的视图中

...
form = InventoryPlotForm(instance=forestinventoryplot,
                         initial={"latitude":forestinventoryplot.latitude})
...

答案 2 :(得分:0)

几年后。一个完整的答案,可以在Django 2.2或更高版本中使用。正如其他人指出的那样,模型形式中仅包含实际的db字段。因此,您需要:

  • 定义自定义模型表单,添加您的@property字段
  • 排除几何字段
  • 在表单的__init__中,获取值,并将其设置为initial
  • 自定义保存方法(在表单或管理员上)

注意:这在更复杂的情况下也适用,在这种情况下,您想抽象出一些更复杂的数据库结构...


class InventoryPlotForm(ModelForm):

    class Meta:
        model = ForestInventoryPlot
        exclude = ("geometry", )

    latitude = forms.WhateverField()

    def __init__(self, *args, **kwargs):
        instance = kwargs.get('instance', None)
        if instance:
            kwargs['initial'] = {'latitude': instance.latitude, }
        return super().__init__(*args, **kwargs)

    def save(self, *args, **kwargs):
        self.instance.latitude = self.cleaned_data['latitude']
        return super().save(*args, **kwargs)