关于 python:在 Django 模型表单中使用模型属性 | 珊瑚贝

Use Model Property in a Django Model Form


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

模型.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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:

1
2
3
4
class InventoryPlotForm(ModelForm):
    class Meta:
        model = ForestInventoryPlot
        exclude = {“geometry”}
  • 与您的问题无关,但请注意 exclude = {“geometry
  • 我简化了表格和模型以使我的观点更加清晰。在这样做时,我没有注意到这一点。感谢您指出。
  • 查看 GeoDjango\\’s forms api,它提供了您可以使用的字段。由于它是一个属性,因此您需要为其创建自己的字段。
  • Burhan,一旦我在纬度上分割了几何字段,我正在创建的字段就不是点几何。那时纵坐标只是一个小数,所以我不相信点域会帮助我。不过,您需要为表单创建一个新字段是正确的,感谢您的帖子。


若干年后。一个完整的答案,在 Django 中工作到 2.2。正如其他人指出的那样,模型表单中只包含真正的数据库字段。因此,您需要:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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, }
        super().__init__(*args, **kwargs)

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

  • 你是最棒的!只是一个细节:init 不返回任何东西,所以它的最后一行只是 super().__init__(*args, **kwargs)。谢谢!


ModelForm 仅自动生成 Django 字段。

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

例如这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
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()}

在你看来

1
2
3
4

form = InventoryPlotForm(instance=forestinventoryplot,
                         initial={“latitude”:forestinventoryplot.latitude})
  • 我基本上实现了您在此处拥有的内容并添加了纬度表单字段,但我得到错误类型对象 \\’InventoryPlotForm\\’ has no attribute \\’latitude\\’。感谢您提供的示例,它有很大帮助,我将不得不修改一下并重新检查。
  • 这非常方便,但知道为什么 super.save() 被调用两次吗?


您的属性不是 Field 实例,因此 ModelForm 无法自动为其生成表单字段。您需要在 InventoryPlotForm 上显式定义一个 latitude 字段,并在表单的 __init__ 和 save 方法中管理其检索和更新。或者,您可以实现自己的 Widget 类并告诉您的 InventoryPlotForm 将其用于 geometry 字段:

1
2
3
4
5
6
7
class InventoryPlotForm(ModelForm):
    class Meta(object):
        widgets = {
            ‘geometry’: MyGeometryWidget,
        }
        …
    …
  • 感谢 Lanzz,我考虑过使用小部件路线,但我认为使用属性来处理这种情况将是一个好方法,主要是因为我认为集成到表单中是微不足道的。也许我会重新考虑,因为小部件可以在其他模型中重复使用。从概念上讲,正如您所说,我需要创建一个表单字段,然后处理该字段的检索和更新,但我很难实现它。让我折腾一会儿,看看我是不是想不通。


来源:https://www.codenong.com/22062104/

微信公众号
手机浏览(小程序)

Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_9074.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
0
分享到:
没有账号? 忘记密码?