如何在自定义管理器中访问模型属性?

时间:2011-11-01 13:51:03

标签: python django django-models filter

我有一个带有DateField的对象的Django模型。我还有两个管理员可以在特定日期范围内过滤这些对象。

class SchoolYearManager(models.Manager):
    def get_query_set(self):
        now = datetime.datetime.now()
        current_year = now.year
        start_date = datetime.date(current_year, 7, 1)
        end_date = datetime.date((current_year + 1), 6, 30)
        return super(SchoolYearManager, self).get_query_set().filter(status=self.model.LIVE).filter(event_date__range=(start_date, end_date))

class PastSchoolYearManager(models.Manager):
    def get_query_set(self):
        current_year = self.model.event_date.year
        start_date = datetime.date(current_year, 7, 1)
        end_date = datetime.date((current_year + 1), 6, 30)
        return super(PastSchoolYearManager, self).get_query_set().filter(status=self.model.LIVE).filter(event_date__range=(start_date, end_date))

class Event(models.Model):
    LIVE = 3
    DRAFT = 4
    STATUS_CHOICES = (
        (LIVE, 'Live'),
        (DRAFT, 'Draft'),
    )
    status = models.IntegerField(choices=STATUS_CHOICES, default=4, help_text="Only entries with a status of 'live' will be displayed publically.")
    event_date = models.DateField()

    objects = Models.Manager()
    school_year_events = SchoolYearManager()
    past_school_year_events = PastSchoolYearManager()

我的第一个经理(SchoolYearManager)按预期工作,返回该日期范围内的事件。但是当我尝试Event.past_school_year_events.all()时,我收到属性错误:“类型对象'事件'没有属性'event_date'”。

我与第二个经理(PastSchoolYearEvents)的目标是包装一个通用年份档案视图,以返回特定年份的日期范围内的事件。

为什么我不能在经理中拨打self.model.event_date

我是以正确的方式来做这件事的吗?如果没有,那么更好的方法是什么?

1 个答案:

答案 0 :(得分:1)

这怎么可行?它可以指的是什么事件日期?当您致电Event.past_school_year_events.all()时,您没有模型实例。顾名思义,self.model指的是模型类。那怎么知道你的日期是什么意思?

我实际上无法弄清楚你想要做什么 - 你将从哪里获得约会。您想从一个活动开始,然后在同一年获得所有其他活动吗?在这种情况下,我怀疑你只想将past_school_year_events变成模型方法,而不是经理。

编辑如果您想从特定年份开始,经理当然是合适的,但您需要将年份作为参数传递给您的经理方法。为此,我在管理器上使用单独的方法,而不是覆盖get_query_set - 事实上,向SchoolYearManager添加另一种方法:

class SchoolYearManager(models.Manager):
    def live_events(self, start_date, end_date):
       return self.filter(status=self.model.LIVE).filter(event_date__range=(start_date, end_date))

    def this_year(self):
        now = datetime.datetime.now()
        current_year = now.year
        start_date = datetime.date(current_year, 7, 1)
        end_date = datetime.date((current_year + 1), 6, 30)
        return self.live_events(start_date, end_date)

    def from_year(self, year):
        start_date = datetime.date(year, 7, 1)
        end_date = datetime.date(year+1, 6, 30)
        return self.live_events(start_date, end_date)

现在你只有一个管理员,它不会覆盖get_query_set,所以你甚至不需要保留默认管理员 - 你可以将其保留为objects。所以你可以这样做:

Event.objects.this_year()  # all this year's events
Event.objects.from_year(2010) # all events from 2010