在 Django 模型中使用 save() 会产生 TypeError

Posted

技术标签:

【中文标题】在 Django 模型中使用 save() 会产生 TypeError【英文标题】:Using save() in Django model produces TypeError 【发布时间】:2017-06-29 17:51:46 【问题描述】:

*****使用 Django 1.11.x 和 Python 3.6*****

我正在尝试学习如何在 Django 模型 (models.py) 中使用 save() 方法。这里有两个字段我想成为自定义的“计算”字段(unique_id 和 age)。

首先我启动字段变量,然后根据现有字段定义方法/属性,然后尝试将方法结果保存到我创建的字段中。

from django.db import models
from dateutil.relativedelta import relativedelta
from datetime import datetime

class Person(models.Model):
    unique_id = models.CharField(max_length=6, primary_key=True)
    age = models.IntegerField()
    last_name = models.CharField(max_length=25)
    birth_date = models.DateField()
    city_of_birth = models.CharField(max_length=25)

    @property
    def get_unique_id(self):
        a = self.last_name[:2].upper()     #First 2 letters of last name
        b = self.birth_date.strftime('%d')     #Day of the month as string
        c = self.city_of_birth[:2].upper()     #First 2 letters of city
        return a + b + c 

    @property
    def get_age(self):
        return relativedelta(self.birth_date.days, datetime.date.now()).years

    def save(self, *args, **kwarg):
        self.unique_id = self.get_unique_id()
        self.age = self.get_age()
        super(Person, self).save(*args, **kwarg)

    def __str__(self):
        return self.unique_id

首先,我创建了 5 个字段。其中 2 个是占位符:unique_id 和年龄。然后我定义了两个@property 方法,每个方法都返回不同类型的结果。 “get_unique_id”函数有效,但我无法将结果存储在数据库中。 “get_age”功能可能会也可能不会起作用。我还没能制作出来。

我的主要问题是如何正确使用 save() 函数来覆盖初始字段值(unique_idage) “计算字段”方法(get_unique_idget_age)。

我的主要问题是,当我添加一个人(使用 /Admin 中的 Person ModelForm)时,它会产生一个 TypeError: 'str' object is在“self.unique_id = self.get_unique_id()”行中不可调用。我目前正在使用管理界面进行测试。

最终,我需要学习如何不在表单中显示这两个字段,因为它们将根据其他字段进行计算。我想我可能在 Meta 上找到了可能有帮助的文档。另外,我希望 unique_id 字段作为主键,所以我在初始字段中添加了这个选项。

我有一个关于 *args 和 **kwargs 的次要问题(对于刚接触 Django 深表歉意)。把他们留在那儿好吗?我真的不确定我需要使用哪些参数(如果有的话),以及是否有必要在代码中包含 *args 和 **kwargs。

注意:对于昨天帮助我使用此应用程序的任何人,我非​​常感谢您的帮助。我认为这与我之前的问题不同,尽管我使用了很多相同的代码。

【问题讨论】:

不要这样做。将年龄设置为单独的字段是没有意义的,因为它会过时。需要时计算。 好的,谢谢。我可以忍受这个。 unique_id 是更重要的一个。 【参考方案1】:

属性不可调用。当您访问self.get_unique_id 时,Python 会在后台调用由@property 修饰的底层方法,在本例中返回一个字符串。你不需要再次调用它,去掉括号:

def save(self, *args, **kwarg):
    self.unique_id = self.get_unique_id
    self.age = self.get_age
    super(Person, self).save(*args, **kwarg)

OTOH,根据@DanielRoseman 的评论,您不需要将年龄存储在数据库中。只需在需要时计算它。您可以将get_age 重命名为age 并删除age 字段,因此age 成为一个属性。

【讨论】:

这成功了!谢谢。 @RonRaney 如果有帮助,您可以考虑接受答案 我的评分不到 15 岁,所以他们不喜欢我的意见 :) @RonRaney 哈哈,您不需要代表接受答案。只需勾选答案旁边箭头下方的复选标记即可。 我开始检查我所有的问题,现在我的声望达到了 21。谢谢!现在我可以投票了。

以上是关于在 Django 模型中使用 save() 会产生 TypeError的主要内容,如果未能解决你的问题,请参考以下文章

在 django 模型自定义 save() 方法中,你应该如何识别一个新对象?

在 Django 模型保存方法中需要帮助

Django:在模型 save() 方法中返回序列化程序 ValidationError

Django:如何使用 pre_save 信号更新模型实例?

使用 Django 时,save() 函数在使用模型表单时不起作用

无法使用 pre_save 信号在 django 模型中保存相关对象