Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'real' multisite support and other minor changes #14

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ How to use
----------

1. Add the `sitemetrics` application to `INSTALLED_APPS` in your settings file (usually `settings.py`)
2. Add `{% load sitemetrics %}` tag to the top of a template (usually base template, e.g. `_base.html`)
2. Add `core.context_processors.request` to TEMPLATE_CONTEXT_PROCESSORS if you are going to use SITEMETRICS_SITE_BY_REQUEST option
3. Add `{% load sitemetrics %}` tag to the top of a template (usually base template, e.g. `_base.html`)


Then you have two options to add metrics counter code to your page:

Expand Down
1 change: 1 addition & 0 deletions docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Getting started
===============

* Add the **sitemetrics** application to INSTALLED_APPS in your settings file (usually 'settings.py').
* Add `core.context_processors.request` to TEMPLATE_CONTEXT_PROCESSORS if you are going to use SITEMETRICS_SITE_BY_REQUEST option
* Add `{% load sitemetrics %}` tag to the top of a template (usually base template, e.g. `_base.html`).
* Use **./manage.py syncdb** to install sitemetrics tables into your database.

Expand Down
8 changes: 8 additions & 0 deletions sitemetrics/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.conf import settings

# Keycodes caching time. Invalidates on keycode changing. Default is one year.
CACHE_TIMEOUT = getattr(settings, 'SITEMETRICS_CACHE_TIMEOUT', 31536000)

# Detect site via HTTP_HOST var. Default is SITE_ID from settings.py
SITE_BY_REQUEST = getattr(settings, 'SITEMETRICS_SITE_BY_REQUEST', False)

132 changes: 80 additions & 52 deletions sitemetrics/templatetags/sitemetrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,84 +2,112 @@
from django.core.cache import cache
from django.db.models import signals
from django.contrib.sites.models import Site

from ..models import Keycode
from ..utils import get_providers_by_alias


# sitemetrics keykodes are stored in Django cache for a year (60 * 60 * 24 * 365 = 31536000 sec).
# Cache is only invalidated on sitemetrics keycode change.
CACHE_TIMEOUT = 31536000
PROVIDERS_BY_ALIAS = get_providers_by_alias()

signals.post_save.connect(lambda **kwargs: cache.delete('sitemetrics'), sender=Keycode, weak=False)
signals.post_delete.connect(lambda **kwargs: cache.delete('sitemetrics'), sender=Keycode, weak=False)
from .. import settings

signals.post_save.connect(
lambda **kwargs: cache.delete('sitemetrics'),
sender=Keycode,
weak=False
)
signals.post_delete.connect(
lambda **kwargs: cache.delete('sitemetrics'),
sender=Keycode,
weak=False
)

register = template.Library()


@register.tag
def sitemetrics(parser, token):
"""Renders sitemetrics counter.

Two notation types are possible:

1. No arguments:
{% sitemetrics %}
Used to render all metrics counters registered and active for the current site.
{% sitemetrics %}
Used to render all metrics counters registered and activated
for the current site in the Django admin interface.
This requires 'Admin site' and 'Sites' Django contribs.

2. Four arguments:
{% sitemetrics by yandex for "138500" %}
Used to render custom metrics counter by definite counter id.
This is a simple template tag with no special requirements.

"""
tokens = token.split_contents()
tokens_num = len(tokens)

if tokens_num == 1:
# Notation Type 1
current_site = Site.objects.get_current()
tokens = token.split_contents()

cached = cache.get('sitemetrics')
if not cached or current_site.id not in cached['keycodes']:
kcodes = current_site.keycode_set.filter(active=True).values()
cache.set('sitemetrics', {'keycodes': {current_site.id: kcodes}}, CACHE_TIMEOUT)
else:
kcodes = cached['keycodes'][current_site.id]

elif tokens_num == 5:
# Notation Type 2
if tokens[1] == 'by' and tokens[3] == 'for':
kcodes = [{'provider': tokens[2], 'keycode': tokens[4].strip('"')}]
else:
raise template.TemplateSyntaxError(
'Four arguments `sitemetrics` tag notation should look like '
'{%% sitemetrics by yandex for "138500" %%}.')
else:
if len(tokens) != 1 and len(tokens) != 5:
raise template.TemplateSyntaxError(
'`sitemetrics` tag requires four or no arguments. '
'E.g. {%% sitemetrics by yandex for "138500" %%} or {%% sitemetrics %%}.')
'`sitemetrics` tag requires four or no arguments. E.g.:'
'{% sitemetrics by yandex for "138500" %} or {% sitemetrics %}'
)

_kcodes = []
for kcode_data in kcodes:
if kcode_data['provider'] in PROVIDERS_BY_ALIAS:
p_cls = PROVIDERS_BY_ALIAS[kcode_data['provider']]
kcode_data['tpl'] = p_cls.get_template_name()
# Get counter parameters.
kcode_data.update(p_cls.get_params())
_kcodes.append(kcode_data)
if len(tokens) == 5 and (tokens[1] != 'by' or tokens[3] != 'for'):
raise template.TemplateSyntaxError(
'Four arguments `sitemetrics` tag notation should look like '
'{% sitemetrics by yandex for "138500" %}.'
)

return sitemetricsNode(_kcodes)
try:
# Notation Type 2
return SitemetricsNode(tokens[2], tokens[4])
except IndexError:
# Notation Type 1
return SitemetricsNode()


class sitemetricsNode(template.Node):
class SitemetricsNode(template.Node):
"""Renders specified site metrics counter from template."""

def __init__(self, keycodes):
self.keycodes = keycodes
self.template = template.loader.get_template('sitemetrics/sitemetrics.tpl')
def __init__(self, provider=None, keycode=None):
self.provider = provider
self.keycode = keycode
self.template = template.loader.get_template(
'sitemetrics/sitemetrics.tpl'
)

def get_keycodes(self, context):
if self.provider and self.keycode:
kcodes = [
{'provider': self.provider, 'keycode': self.keycode.strip('"')}
]
else:
if settings.SITE_BY_REQUEST:
request = context.get('request')
current_site = Site.objects.get(domain=request.get_host())
else:
current_site = Site.objects.get_current()

cached = cache.get('sitemetrics')

if not cached or current_site.id not in cached['keycodes']:
kcodes = current_site.keycode_set.filter(active=True).values()
cache.set(
'sitemetrics',
{'keycodes': {current_site.id: kcodes}},
settings.CACHE_TIMEOUT
)
else:
kcodes = cached['keycodes'][current_site.id]

_kcodes = []
providers = get_providers_by_alias()
for kcode_data in kcodes:
if kcode_data['provider'] in providers:
p_cls = providers[kcode_data['provider']]
kcode_data['tpl'] = p_cls.get_template_name()
# Get counter parameters.
kcode_data.update(p_cls.get_params())
_kcodes.append(kcode_data)

return _kcodes

def render(self, context):
return self.template.render(template.Context({'keycodes': self.keycodes}))
return self.template.render(
template.Context({'keycodes': self.get_keycodes(context)})
)