确定startdate和enddate是否可以看到条目

时间:2013-10-15 08:43:50

标签: python django

我有一个包含三个字段的模型,以确定文本是否应该在模板中可见。

如果选中了布尔字段,它将覆盖两个日期字段。

如果未选中布尔字段,则只应在startdate过去时返回True,如果设置了enddate,则只有在将来设置日期时才返回true。

我该怎么做?

这是我尝试过的,但不能像我想的那样工作:

class Entry(models.Model):
    name = models.CharField(max_length=200)

    visible = models.BooleanField(default=False, help_text="If checked, the text will be visible, even if the datefield is set")
    visible_start = models.DateTimeField(help_text="Visible from", blank=True, null=True)
    visible_end = models.DateTimeField(help_text="Visible to", blank=True, null=True)

    def is_visible(self):
        now = timezone.now()

        if not self.visible:
            if self.visible_start and now < self.visible_start:
                return False

            if self.visible_end and now > self.visible_end:  
                return False            

        return True

2 个答案:

答案 0 :(得分:3)

您可以实施经理,例如(另):

class VisibleEntryManager(models.Manager):
    def get_query_set(self):
        now = datetime.now()
        return super(VisibleEntryManager, self).get_query_set()\
               .filter(visible=True)\
               .filter(visible_start__gte=now, visible_end__lte=now) # Or use Q objects

class Entry(models.Model):
    # other stuff
    visible_objects = VisibleEntryManager()

编辑:管理员使用默认管理器(通过调用_default_manager类上的Model)。如果你想推迟管理对象,你可以这样做:

class EntryAdmin(admin.ModelAdmin):
    # other stuff

    def queryset(self, request):
        if request.user.is_superuser or request.user.is_staff:  # example rule
            qs = self.model.objects.all()  # could be admin_objects if you want to set 
                                           # .objects as the default filtered option on 
                                           # the Entry model.
            ordering = self.get_ordering(request)
            if ordering:
                qs = qs.order_by(*ordering)
            return qs
        return super(ProductAdmin, self).queryset(request)

答案 1 :(得分:1)

开始和停止有null = True。因此,您可以检查:Null < nowNull > Now(始终为假)。如果start和stop在现在的标准范围内,则下面的代码将返回True。

def is_visible(self):
    now = datetime.now()

    if self.is_visible:
        # is_visible field is checked.
        return True

    #elif self.visible_start < now and self.visible_stop == Null:
    #    return True

    elif self.visible_start < now and self.visible_stop > now:
        # Start is before now and stop is after now.
        return True

    else:
        # All other options
        return False

更新

我添加了这个,以显示何时使用过滤器,方法和管理员。

看起来你想做这样的事情:

# views.py
objects = Entry.objects.all()

# template.html
{% for obj in objects %}
    {% if obj.is_visible %}
        {{ obj.title }}
    {% endif %}
{% endfor %}

不要这样做!这将循环所有条目(可以是很多)。这是一场表演噩梦!首先过滤条目。像这样:

# views.py
now = datetime.now()    
objs0 = Entry.objects.filter(visible=True)
objs1 = Entry.objects.filter(visible_start__lte=now, visible_stop__gt=now)
objects = objs0 | objs1

# template.html
{% for obj in objects %}
    {{ obj.title }}
{% endfor %}

这只会循环抛出相关对象。如果在项目中多次出现此列表,并且您注意到多次在上面查看,那么请考虑模型管理器。像@HeddeVanDerHeide建议的那样。编写完经理后,您可以获得所有可见对象:

objects = Entry.visible_objects.all()

为什么不直接过滤模型方法?

objects = Entry.objects.filter(is_visible=True)

因为Django没有那样工作。对数据库执行查询,数据库不知道方法。但模型方法有什么用呢?如果要显示条目之间的差异,请使用模型方法:

# models.py
def is_important(self):
    now = datetime.now()
    if self.start < now and self.stop > now:
        return True
    else:
        return False

# views.py
objects = Entries.objects.all()

# template.html
{% for obj in objects %}
    <p{% if obj.is_important %} class="highlight"{% endif %}>{{ obj.title }}</p>
{% endfor %}

当你想在管理列表显示中显示一个布尔值时,模型方法可以实现这一点:

class EntryAdmin(admin.ModelAdmin):
    list_display = ('title', 'is_visible')

来自文档:

  

在模型上定义自定义方法以添加自定义“行级”   对象的功能。而管理方法的目的是   做“全桌”的事情。