【问题标题】:Best way to keep data in an object updated based on some logic?根据某些逻辑更新对象中数据的最佳方法?
【发布时间】:2016-05-03 16:35:47
【问题描述】:

我正在创建一个应用,其中“Episode”对象具有“air_time”和“air_status”字段。

class Episode(models.Model):
    air_time = models.DateTimeField()
    air_status = models.TextField(default="UPCOMING")
    # air_status can contain UPCOMING, LIVE or VOD in the original code

我想根据“air_time”字段更新“air_status”字段。 我应该在应用程序的哪个位置处理和更新“air_status”字段?我在想两个选择:

  1. 根据视图中的对象请求,视图 将更新“air_status”字段。缺点是如果对象从未加载,则字段“air_status”不会在数据库中更新。
  2. 以某种方式检查模型文件以在当前时间等于“air_time”时更新“air_status”。

我知道如何执行选项 1,但不知道选项 2。最好的解决方案是什么?谢谢!

【问题讨论】:

  • 不要在数据库中存储逻辑,而是查询它的数据
  • 您的意思是删除“air_status”字段并在视图中找出它以将其传递给模板?这样做的问题是,我无法在所有对象上制作三个类别“VOD”、“LIVE”和“UPCOMING”。
  • 是的。通过它的声音,可以根据 air_time 确定状态(可能也需要持续时间)
  • 因此,如果我想获得已经播出的分页器中的所有剧集,我需要做这样的事情(?): Episode.objects.all.filter(air_time__lt=datetime.日期时间.now())。我担心这会占用大量资源,但我可能会选择这个选项。

标签: python mysql django database


【解决方案1】:

您可以动态地执行此操作,而无需在数据库中存储任何内容。有两种方法可以做到这一点。

模型属性

最简单的方法是向模型添加一个属性。缺点是不能通过这个字段查询。

class Episode(models.Model):
    air_time = models.DateTimeField()
    end_time = models.DateTimeField()

    @property
    def air_status(self):
        if self.air_time < now():
            return 'UPCOMNG'
        elif self.air_time >= now() and self.end_time < now():
            return 'LIVE'
        else:
            return 'VOD'

现在您可以像访问对象上的任何其他属性一样轻松访问它:episode.duration

Custom Queryset/Manager

如果您必须通过该字段进行查询,您还可以在模型中添加自定义管理器。

class EpisodeManager(models.Manager):
    def upcoming(self):
        return self.get_queryset().filter(air_time__lt=now())

    def live(self):
        return self.get_queryset().filter(
            air_time__gte=now(),
            end_time__lt=now()
        )

    def vod(self):
        return self.get_queryset().filter(
            end_time__lte=now()
        )

class Episode(models.Model):
    ...

    objects = EpisodeManager()

现在您可以请求特定类型的剧集:例如Episode.objects.vod()

当然,您可以继续扩展它并实现custom queryset,这样您就可以采用任意Episode 模型查询并像Episode.objects.filter(title='Game of Thrones').live() 一样对其进行过滤。

【讨论】:

  • 哇!惊人的答案,我还没有看到经理使用过,但它们看起来真的很酷。我将实现这两​​种方法。最后一个问题:基于 .air_status 我想更改页面上某个元素的 css/html。我是正确的,这个逻辑应该在模板本身中,所以像这样: {% if episode.air_status == 'LIVE' %} live css/html header (red color) {% else } not live css/html header (蓝色){% endif % }。这是做这种事情的首选方式吗?
  • 我会将其实现为custom filter,这样您就不必重复自己了。然后你可以像这样使用它:episode.status|status_color。如果您想要的不仅仅是颜色,请在模型上实现所有三种状态的属性:episode.is_liveepisode.is_upcomingepisode.is_vod 并执行{% if episode.is_live %}...{% endif %}。记住DRY 原则。
  • 我确实想要每个状态的一些自定义 html。我也会将这三个属性作为函数添加到模型中。只是为了确保:自定义 HTML 永远不应该在模型中,而是在模板中,对吗? {% if episode.is_live %}

    LIVE{% endif %}{% if episode.is_vod %}

    观看视频点播!{% endif %}{% if episode.is_upcoming %}

    即将到来!

    {% endif %}。非常感谢您的帮助 o//。
猜你喜欢
  • 2021-10-23
  • 1970-01-01
  • 2019-01-30
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多