【问题标题】:How to define range of months for any year on Django model?如何在 Django 模型上定义任何年份的月份范围?
【发布时间】:2011-10-11 14:38:00
【问题描述】:

我有一个名为 Event 的 Django 模型,其中包含事件日期的日期字段:

class Event(models.Model):
    event_date = models.DateField()

我希望能够在模型上设置一个方法来判断活动是“春季学期”活动还是“秋季学期”活动。

春季学期将定义为一月至五月。秋季是八月到十二月。

我的目标是能够在一年的通用事件列表中按任一学期进行过滤。

我将如何编写定义每个学期的方法?

【问题讨论】:

    标签: python django date methods


    【解决方案1】:

    一种方法是:

    class SpringSemesterEventManager(models.Manager):
        def get_query_set(self):
            return super(SpringSemesterEventManager, self).get_query_set() \
                .filter(is_spring_semester=True)
    
    class FallSemesterEventManager(models.Manager):
        def get_query_set(self):
            return super(FallSemesterEventManager, self).get_query_set() \
                .filter(is_fall_semester=True)
    
    class Event(models.Model):
        event_date = models.DateField()
    
        @property
        def is_spring_semester(self):
            month = self.event_date.month
            return True if month >= 1 and month <= 5 else False
    
        @property
        def is_fall_semester(self):
            month = self.event_date.month
            return True if month >= 8 and month <= 12 else False
    
        objects = models.Manager()
        spring_semester = SpringSemesterEventManager()
        fall_semester = FallSemesterEventManager()
    

    然后在一个视图中你可以这样做:

    fall_events = Event.fall_semester.all()
    

    希望对你有所帮助。

    【讨论】:

    • 等等,您正在对实例的属性进行过滤(它使用 SQL WHERE 子句)?这怎么能行?即使它确实有效,它也会非常低效,因为它意味着迭代查询集的所有对象。
    • OP 要求提供一种模型方法,该方法可以确定 Event 实例是“spring”还是“fall”事件。无论您是检索一个对象还是数百个对象,确定月份是否属于特定范围都需要对每个对象进行迭代。更好的方法是在保存模型时设置一个单独的值,该值检查 event_date 并确定“spring/fall/whatever”。然后可以对该字段进行索引以进行非常快速的搜索。当我有空闲时间时,我会更新示例。
    • 我认为不需要单独的值。只需在管理器上更新这些方法,返回一个像这样过滤的 QuerySet:return super(SpringSemesterEventManager, self).get_query_set().filter(event_date__month__gte=1, event_date__month__lte=5),然后从模型中删除这些属性/方法。
    • 实际上,将属性保留在模型上可能是个好主意,这样您就可以查询实例,但不能查询管理器中的属性。
    • @Mandx,后缀 __month__lte 在 Django 1.4 上对我不起作用(我得到一个 AttributeError)。也许这是旧的 Django 版本,有人可以确认这是否有效吗?
    【解决方案2】:

    你看过 django 的 Models 方法吗?你可以找到他们here

    class Event(models.Model):
        event_date = models.DateField()
    
        def get_season(self):
            import datetime
            """
            Returns the event's specific season
            """
            if 1 <= datetime.date.today().month < 4:
                return "Winter event"
    

    显然上面的代码不正确,但你知道该怎么做。

    【讨论】:

      【解决方案3】:

      您可以简单地在日期范围内使用过滤器,使用 __gt(大于)和 __lt(小于)运算符:

      Event.objects.filter(event_date__gt=datetime.date(2011, 1, 1), event_date__lt=(datetime.date(2011,6,1))
      

      或者您可以将学期写入数据库,例如,您可以覆盖默认的 save() 方法,以便在您保存新事件或现有事件时自动完成。所以模型是:

      class Event(models.Model):
          event_date = models.DateField()
          semester = models.CharField(max_length=10)
      
      def save(self, *args, **kwargs):
          # determine if the even is in the spring or fall
          if self.event_date.month in [1,2,3,4,5]
              self.semester = 'spring'
          elif self.event_date.month in [8,9,10,11,12]
              self.semester = 'fall'
          super(Event, self).save(*args, **kwargs) # Call the "real" save() method.
      

      然后就可以简单查询Event.objects.filter(semester = 'spring')

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-14
        • 1970-01-01
        • 2019-01-07
        • 1970-01-01
        • 1970-01-01
        • 2017-12-10
        • 2014-04-24
        • 1970-01-01
        相关资源
        最近更新 更多