【问题标题】:How to automatically change model fields in django如何在 django 中自动更改模型字段
【发布时间】:2017-01-06 12:00:12
【问题描述】:

我有一个模型,我想知道是否可以设置触发模型字段更改的条件。例如,我有一个模型

class BillboardTracker(models.Model):
    client_name = models.CharField(max_length=400)
    entry_date = models.DateTimeField(default=datetime.now)
    duration = models.PositiveIntegerField()
    expiry_date = models.DateField()
    is_expired = models.BooleanField(default=False)

我想知道是否有可能在模型中具有使 is_expired 在到期日期结束时等于 True 的函数。我试过这个

def expire(self):
     if datetime.now == self.expiry_date:
        self.is_expired = True

但它不起作用。有可能实现吗?

【问题讨论】:

  • 可以,但您需要调用 now 函数:datetime.now()。另请注意,您可能想要检查 now 是否大于到期日期,否则只有在到期的同时调用它才会起作用。

标签: python django django-models


【解决方案1】:

使用@property

​​>

这里最简单的事情是根本没有 is expired 字段!这不是必需的。你需要的是一个财产。

class BillboardTracker(models.Model):
    client_name = models.CharField(max_length=400)
    entry_date = models.DateTimeField(default=datetime.now)
    duration = models.PositiveIntegerField()
    expiry_date = models.DateField()

    @property
    def is_expired(self):
        if datetime.now > self.expiry_date:
            return True
        return False

请记住,如果该字段与具有简单计算的另一个字段相同,则您在数据库中没有字段。这会自动消除您必须将项目标记为过期的头痛。

如果您想了解某个对象是否已过期。

 if instance.is_expired == True:
    print 'yes, that ones gone'

过滤

如果您想检索一整套已过期的对象

BillboardTracker.objects.filter(expiry_date__le=datetime.now())

这就是为什么我提到你不需要存储一个可以轻松计算的字段。

指标优势

在大多数 RDBMS 中,布尔字段(例如您的 is_expired 列)无法有效地建立索引。所以这实际上意味着如果您在 expiry_date 字段上创建索引,上述查询将比对该布尔字段的查询更快。

【讨论】:

  • 感谢您的快速回复。现在,当我定义该函数时,是否需要像 BillboardTracker.expire 一样调用它?或者每当我创建一个新对象时该函数都会自动运行
  • 现在不需要将过期状态存储在数据库中,因此不需要自动运行。
  • 抱歉所有问题,我是 django 新手,我正在使用 djangoframework 视图集,如何将其添加到我的视图集中。是在 perform_create 函数中吗?
  • 正如我所说,现在数据库中没有字段,因为不需要,所以没有必要拥有它在 perform_create 或任何东西中。您的所有创建/更新操作都可以忽略该字段。该领域纯粹是一个虚拟领域:)
【解决方案2】:

你需要在这个函数中做两处改变, 首先使用 datetime.now(),其次,

您可能希望像这样更新您的逻辑:

def expire(self):
     if datetime.now() >= self.expiry_date:
        self.is_expired = True
        return True
     else:
        return False

因为有时这两个值可能不完全相同,但仍然 BillboardTracker 需要 is_expired = True 对于所有以前的日期。

在你看来:

 def your_view(request):
    instance = BillboardTracker.objects.get(id=some_id)
    if instance.is_expired() == True:
        print 'expired'
    else:
        print 'fresh'

【讨论】:

  • 定义了这个函数后,如何运行?
  • @HackAfro 在您的视图中,每当您在表中保存任何对象时,请检查 object.expire() 是否返回 true 或 false。
  • @HackAfro 更新了我的答案。请立即查看。
  • 谢谢我正在使用 DRF 视图集,这会以同样的方式工作吗?
  • @HackAfro 在 rest api 中,模型的行为也是一样的。它也适用于此。
猜你喜欢
  • 2015-06-15
  • 1970-01-01
  • 2020-01-22
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 2020-05-07
  • 1970-01-01
相关资源
最近更新 更多