First you need a context processor to get the banner for you:
# 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}
Tie that into your settings.py TEMPLATE_CONTEXT_PROCESSORS
setting. Then, in each of your templates, you'll automatically have a banner
variable you can use to access the banner to load (assuming there's at least one banner available).
The context processor is a little complicated, so I should probably walk you through it. First, it attempts to retrieve a list of "seen" banners from the session. This is then used to exclude those banners from the queryset (so the so the same user won't get the same banner again). An IndexError
will occur if there's not at least one available banner, so we catch that. If it's because the user has already seen them all, we kill the session var and try to get a banner again without excluding any. Otherwise, there's really no banners available, so we simply return an empty context.
If we are able to get a banner, then we add its id to the session var so it won't be repeated and then we return the context with the banner included.