Max Ferreira
Max Ferreira

Reputation: 468

Ordering by model method

I have a Opening Times table, and I need to sort the items according to the "opening time", so it will show 'open now', and then 'closed now' items. But I can't filter by a model method.

models.py

class Company(ImageBaseModel):
    class Meta:
        verbose_name = _(u"Empresa")
        verbose_name_plural = _(u"Empresas")
        ordering = ('order',)
    user                            = ForeignKey('auth.User', verbose_name=_(u"Responsável"), null=True, blank=True)

    # Admin fields
    slug            = SlugField(verbose_name=_(u'Slug / URL'), blank=True, null=True)
    order           = PositiveIntegerField(verbose_name=_(u"Ordem"), null=True, blank=True)

    def __unicode__(self):return u'%s'%self.title
    def get_address(self):
        if self.cep and self.address and self.city and self.number: return True

    def isopen(self):
        now = datetime.now()
        nowTime = time(now.hour, now.minute, now.second)
        ohs = self.opening_times.filter(company__slug=self.slug)
        status = False
        for oh in ohs:
            is_open = False
            # start and end is on the same day
            if oh.weekday == now.isoweekday() and oh.fromHour <= nowTime and nowTime <= oh.toHour:
               is_open = oh

            # start and end are not on the same day and we test on the start day
            if oh.weekday == now.isoweekday() and oh.fromHour <= nowTime and ((oh.toHour < oh.fromHour) and (nowTime < datetime.time(23, 59, 59))):
                is_open = oh

            # start and end are not on the same day and we test on the end day
            if (oh.weekday == (now.isoweekday()-1)%7 and oh.fromHour >= nowTime and oh.toHour >= nowTime and oh.toHour < oh.fromHour):
                is_open = oh
                #print " 'Special' case after midnight", oh

            if is_open is not False:
                status = True
        return status
    def hasOt(self): #have opening times registry
        return len(self.opening_times.all()[:1]) == 1

class OpeningHours(Model):
    class Meta:
        verbose_name = _(u"Horário de Abertura")
        verbose_name_plural = _(u"Horários de Abertura")
        unique_together = ('company', 'weekday')
    company = ForeignKey(Company, related_name="opening_times", verbose_name=_(u"Empresa"))
    weekday = IntegerField(choices=WEEKDAYS, verbose_name=_(u"Dia da Semana"))
    fromHour = TimeField(verbose_name=_(u"Abre ás:"), null=True, blank=True)
    toHour = TimeField(verbose_name=_(u"Fecha ás:"), null=True, blank=True)

    def __unicode__(self):
        return "%s %s (%s - %s)" % (self.company, self.weekday, self.fromHour, self.toHour)

views.py

def home(request):
    companies       = Company.objects.filter(published=True).order_by('opening_times')
    food_companies  = companies.all()[0:5] #here I'll have to filter only food companies open now. 

I need to something like food_companies.order_by('open_now_first'), but I don't know how can I do that.

Upvotes: 0

Views: 47

Answers (1)

xnx
xnx

Reputation: 25478

order_by is applied at the database level (ie in the raw SQL) so you can't call a function with it. You can get all your food_companies and sort them using isopen as a key, though. Something like:

sorted_companies = sorted(food_companies.objects.all(),
                          key=lambda food_company: food_company.isopen())

Upvotes: 1

Related Questions