【问题标题】:Django Model Method or Calculation as Field in DatabaseDjango 模型方法或计算作为数据库中的字段
【发布时间】:2017-06-28 14:24:21
【问题描述】:

使用 Django ~=1.11 和 Python 3.6

我需要将“计算”变量作为字段存储在 Django 模型数据库中。

这是一个模型:

from django.db import models
from datetime import date

class Person(model.Model)
    "Last Name"
    last_name = models.CharField(max_length=25)

    "Birthday"
    birth_date = models.DateField()

    "City of birth"
    city_of_birth = models.CharField(max_length=25)

我正在使用这些字段创建唯一 ID。具体来说,我将每个字段的部分组合成一个字符串变量(详情如下)。我能够让它作为属性工作,但我不知道如何在数据库中存储计算字段。

"Unique ID"
def get_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 
unique_id = property(get_id)

我想对 Age 做类似的事情。这是我的计算:

"Age calculated from Birth Date"
def get_age(self):
    return int((datetime.date.now() - self.birth_date.days) / 365.25)
age = property(get_age)

所以我想将 UniqueID 和 Age 变量存储在数据库中,作为 Person 模型中的字段。执行这些操作时的最佳做法是什么?我是否需要先初始化字段,然后对这些字段进行某种更新查询?

注意:据我了解,当前使用“属性”的代码可用于在视图中进行渲染,但它并未存储在数据库中。

提前致谢!请帮助我改进我已有的。

更新: 这是对我有用的代码。问题是我需要在 self.unique_id=self.get_unique_id 之后删除 save() 部分中的括号。建议从数据库中删除年龄,并将其保留为属性。

class Person(models.Model):
    unique_id = models.CharField(max_length=6, blank=True)
    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 age(self):
        return relativedelta(self.birth_date.days, datetime.date.now()).years

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

    def __str__(self):
        return self.unique_id

【问题讨论】:

  • 您已经完成了大部分工作。你只需要为你的模型创建一个自定义保存函数就可以了。
  • 请提供具体代码的答案。到目前为止,我还没有找到实用的答案。

标签: python django methods django-models calculated-field


【解决方案1】:

您必须覆盖您的模型Personsave 方法并在模型中创建unique_idage 字段。

from dateutil.relativedelta import relativedelta
from datetime import datetime

class Person(model.Model)
     unique_id = models.CharField(max_length=25)
     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, **kwargs):
          self.unique_id = self.get_unique_id
          self.age = self.get_age
          super(Person, self).save(*args, **kwargs)

更新:以前 self.get_unique_idself.get_age 是使用 '()' 调用的,这对于类属性来说不是必需的。

【讨论】:

  • 另外我建议使用relativedelta 来计算日期时间差异。
  • 我正在搜索如何使用 relativedelta 但尚不确定如何执行此操作。如果您可以编辑您的代码,我将不胜感激!
  • 见上文。需要在“self.get_unique_id()”之后删除括号。谢谢!
  • 但是 save() 将在您每次 save() 时运行。您不应该指定仅在创建时执行此操作吗?
【解决方案2】:

一个模型有一个clean 方法来处理这种事情:

此方法应用于提供自定义模型验证,并在需要时修改模型上的属性。例如,您可以使用它来自动为字段提供值,或者进行需要访问多个字段的验证

所以松开属性并添加一个名为“unique_id”的字段,它应该是一个 CharField。将get_id 重命名为clean 并将return 语句替换为:

self.unique_id = a + b + c

如果您确定这始终会生成唯一的字符串,请考虑将此字段设置为主键。但是,如果此模型已经迁移,则不能将其命名为 id,因为 Django 已经为您创建了一个字段 id 作为 AutoField,因此如果您设置为名称,则需要两次迁移id'(您可以稍后将其压缩)。

【讨论】:

  • 谢谢。我想我现在会遇到的问题是表格。如果我进入 /Admin 创建一个对象,它需要我为 UniqueID 和 Age 输入一个值。我希望在输入表格后计算这些。我尝试在字段类型选项中添加“required=False”,但它给了我错误。
  • 您可以从 ModelAdmin 中exclude the field,因为它在后台使用ModelForm。此外,模型字段上的“blank=True”使其不是必需的,但要使其正常工作,它不能是主键。
  • 知道如何处理这个问题吗?当我单击保存时,此模型的 ModelForm 需要这些值。我不确定如何将其包含在视图中。我应该为此打开另一个问答吗?异常值:save() 缺少 2 个必需的位置参数:'get_unique_id' 和 'get_age'
  • 请做。你可能已经以我无法预测的方式修改了你的代码:)
  • 感谢您的帮助。看来我需要查看代码,因为您的建议对我不起作用。我是 Python 和 Django 的新手。
猜你喜欢
  • 2021-07-30
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多