我有横幅模型
class SiteBanner( models.Model ):
banner = models.FileField( storage=s3_storage, upload_to = 'banners/', null=True, blank=True )
order = models.PositiveIntegerField ( default=0 )
default = models.BooleanField ( default = False )
我想在每个用户点击或每个网站页面上显示不同的横幅。当我为横幅设置default
到True
时,它将被禁用,然后此横幅将显示在每个页面上。
这可能吗?如果是,那将是一个优雅的解决方案? cookies
是否有助于实现这一目标?
答案 0 :(得分:2)
首先,您需要一个上下文处理器来为您获取横幅:
# your_app/context_processors.py
def get_banner(request):
seen_banners = request.session.get('seen_banners', [])
try:
banner = SiteBanner.objects.exclude(pk__in=seen_banners, default=False).order_by('order')[0]
except IndexError:
if seen_banners:
del request.session['seen_banners']
try:
banner = SiteBanner.objects.exclude(default=False).order_by('order')[0]
except IndexError:
return {}
else:
return {}
else:
if seen_banners:
request.session['seen_banners'].append(banner.pk)
request.session.modified = True
else:
request.session['seen_banners'] = [banner.pk]
return {'banner': banner}
将其与settings.py TEMPLATE_CONTEXT_PROCESSORS
设置相关联。然后,在每个模板中,您将自动拥有一个banner
变量,可用于访问要加载的横幅(假设至少有一个横幅可用)。
上下文处理器有点复杂,所以我应该引导您完成它。首先,它尝试从会话中检索“看到的”横幅列表。然后,这用于从查询集中排除这些横幅(因此同一用户不会再次获得相同的横幅)。如果没有至少一个可用横幅,则会出现IndexError
,因此我们会抓住它。如果是因为用户已经看过它们,我们会杀死会话var并尝试再次获得横幅而不排除任何横幅。否则,实际上没有可用的横幅,所以我们只返回一个空的上下文。
如果我们能够获得横幅,那么我们将其id添加到会话var中,这样它就不会重复,然后我们返回包含横幅的上下文。
答案 1 :(得分:1)
(1)让每个页面都从显示横幅的模板继承。在此处了解模板继承:https://docs.djangoproject.com/en/dev/topics/templates/#template-inheritance
(2)使用上下文处理器选择横幅,并将其插入上下文中;也就是说,将其作为模板中的变量提供。在此处了解上下文处理器:https://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext
编写代码留给读者练习。