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

Adding views #78

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
68e05d8
Beginning to add more views.
eturpin Jun 28, 2019
ffe55e0
Beginning to add more views.
eturpin Jun 28, 2019
7d9229e
In progress of adding views.
eturpin Jul 1, 2019
b4104bd
In progress of adding views.
eturpin Jul 11, 2019
48175ea
In progress of adding views.
eturpin Jul 12, 2019
cec2f3a
In progress of adding views.
Jul 17, 2019
d390e1f
In progress of adding views.
eturpin Jul 17, 2019
29600ae
In progress of adding pagination.
eturpin Jul 18, 2019
59717d5
In progress of refining views.
eturpin Jul 19, 2019
2487d19
Fixed some formatting, and added tooltips to links.
Jul 22, 2019
444399e
Forgot to add migration.
Jul 22, 2019
fd2a86e
Removed bad migration.
Jul 22, 2019
07be2b7
Fixing migration.
Jul 22, 2019
ef9d73b
Setting url field back to text field. Looks like can't index URLs.
Jul 22, 2019
bb5d0bf
Added migrations.
Jul 22, 2019
2847fff
Fixed url to page overview.
eturpin Jul 23, 2019
b9eef59
Fixed paging on visitor_visits.
eturpin Jul 23, 2019
9f244fa
Added time range filters to all appropriate views.
eturpin Jul 24, 2019
dc968e7
Made date filters to carry over to consecutive views.
Jul 27, 2019
de80b3d
Fexed page_detal.html
eturpin Aug 2, 2019
c67b99d
Refactoring code for DRY principle. Adding checks for enabled and
eturpin Aug 2, 2019
cb0d0f4
In progress of writing tests for views.
eturpin Aug 5, 2019
5f156b5
In progress of writing tests for views.
eturpin Aug 5, 2019
5402966
Merge branch 'master' of github.com:eturpin/django-tracking2
Aug 23, 2019
4127166
Fixed merge and a few template bugs.
eturpin Aug 23, 2019
211b7e2
Added # pageviews to visitor overview visits. MA-378.
eturpin Sep 4, 2019
7f20e92
Fixed erroneous results on visit overview.
eturpin Jan 28, 2020
17d6987
Got tests passing
eturpin Feb 3, 2020
9fcd313
Added last_pageview to user_stats.
eturpin Feb 4, 2020
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
28 changes: 12 additions & 16 deletions tracking/managers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from __future__ import division

import logging

from datetime import timedelta
from django.utils import timezone
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models import Count, Avg
from django.db.models import Count, Avg, Sum, Max
from tracking.settings import TRACK_PAGEVIEWS, TRACK_ANONYMOUS_USERS
from tracking.cache import CacheManager

log = logging.getLogger(__file__)

class VisitorManager(CacheManager):
def active(self, registered_only=True):
Expand Down Expand Up @@ -163,25 +166,18 @@ def user_stats(self, start_date=None, end_date=None):
else:
user_kwargs['visit_history__start_time__isnull'] = False
visit_kwargs['start_time__isnull'] = False

users = list(get_user_model().objects.filter(**user_kwargs).annotate(
visit_count=Count('visit_history'),
users = get_user_model().objects.filter(**user_kwargs).annotate(
visit_count=Count('visit_history', distinct=True),
time_on_site=Avg('visit_history__time_on_site'),
page_count=Count('visit_history__pageviews', distinct=True),
pages_per_visit=Count('visit_history__pageviews', distinct=True)/Count('visit_history', distinct=True),
last_pageview=Max('visit_history__pageviews__view_time'),
).filter(visit_count__gt=0).order_by(
'-time_on_site',
get_user_model().USERNAME_FIELD,
))

# Aggregate pageviews per visit
for user in users:
user.pages_per_visit = user.visit_history.filter(
**visit_kwargs
).annotate(
page_count=Count('pageviews')
).filter(page_count__gt=0).aggregate(
pages_per_visit=Avg('page_count'))['pages_per_visit']
# Lop off the floating point, turn into timedelta
user.time_on_site = timedelta(seconds=int(user.time_on_site))
)

return users


Expand Down
25 changes: 25 additions & 0 deletions tracking/migrations/0003_auto_20190722_1418.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
import django.utils.timezone


class Migration(migrations.Migration):

dependencies = [
('tracking', '0002_auto_20180918_2014'),
]

operations = [
migrations.AlterField(
model_name='pageview',
name='view_time',
field=models.DateTimeField(db_index=True),
),
migrations.AlterField(
model_name='visitor',
name='start_time',
field=models.DateTimeField(editable=False, default=django.utils.timezone.now, db_index=True),
),
]
4 changes: 2 additions & 2 deletions tracking/models.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Visitor(models.Model):
# Update to GenericIPAddress in Django 1.4
ip_address = models.CharField(max_length=39, editable=False)
user_agent = models.TextField(null=True, editable=False)
start_time = models.DateTimeField(default=timezone.now, editable=False)
start_time = models.DateTimeField(default=timezone.now, editable=False, db_index=True)
expiry_age = models.IntegerField(null=True, editable=False)
expiry_time = models.DateTimeField(null=True, editable=False)
time_on_site = models.IntegerField(null=True, editable=False)
Expand Down Expand Up @@ -93,7 +93,7 @@ class Pageview(models.Model):
referer = models.TextField(null=True, editable=False)
query_string = models.TextField(null=True, editable=False)
method = models.CharField(max_length=20, null=True)
view_time = models.DateTimeField()
view_time = models.DateTimeField(db_index=True)

objects = PageviewManager()

Expand Down
2 changes: 2 additions & 0 deletions tracking/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
TRACK_REFERER = getattr(settings, 'TRACK_REFERER', False)

TRACK_QUERY_STRING = getattr(settings, 'TRACK_QUERY_STRING', False)

TRACK_PAGING_SIZE = getattr(settings, 'TRACK_PAGING_SIZE', 100)
22 changes: 4 additions & 18 deletions tracking/templates/tracking/dashboard.html
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,10 @@
</head>
<body>
<h1>Dashboard - django-tracking2</h1>
<div id="tracking-filters">
<form method="GET">
{{ form.as_table }}
<input type="submit" name="submit" value="submit" />
</form>
</div>
<div id="tracking-info">
<p>
Visitor tracking began on
{{ track_start_time|date:"Y-m-d H:i:s" }}
</p>
{% if warn_incomplete %}
<p class=warning>
The start time precedes the oldest tracked visitor, thus
the stats are not complete for the specified range.
</p>
{% endif %}
</div>
{% include "tracking/snippets/tracking_filters.html" %}
{% if has_pageviews %}
<a href={% url "tracking-page-overview" %}>Page centric statistics</a>
{% endif %}
<div id="tracking-stats">
{% include "tracking/snippets/stats.html" %}
</div>
Expand Down
49 changes: 49 additions & 0 deletions tracking/templates/tracking/page_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ page_url }} Details - django-tracking2</title>
</head>
<body>
<h1>{{ page_url }} Details - django-tracking2</h1>
{% include "tracking/snippets/tracking_filters.html" %}
<div id="tracking-stats">
<dl>
<dt>Total Views</dt>
<dd>{{ total_views }}</dt>
<dt># of Unique Visitors</dt>
<dd>{{ visitors }}</dt>
</dl>
{% if pageviews.has_previous %}
<a href="{% url 'tracking-page-detail' %}?page_url={{ page_url }}&page={{ pageviews.previous_page_number }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}">previous</a>
{% endif %}
{% if pageviews.has_next %}
<a href="{% url 'tracking-page-detail' %}?page_url={{ page_url }}&page={{ pageviews.next_page_number }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}">next</a>
{% endif %}
<table>
<caption>Pageviews</caption>
<thead>
<th>Time</th>
<th>User</th>
<th>Method</th>
<th>URL</th>
</thead>
<tbody>
{% for pv in pageviews %}
<tr>
<td><a href="{% url 'tracking-visitor-page-detail' user_id=pv.visitor.user.pk %}?page_url={{ page_url }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}" title="View visits by {% firstof pv.visitor.user.get_full_name pv.visitor.user %} involving {{ page_url }}">{{ pv.view_time|date:"Y-m-d H:i:s" }}</a></td>
<td><a href="{% url 'tracking-visitor-page-detail' user_id=pv.visitor.user.pk %}?page_url={{ page_url }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}" title="View visits by {% firstof pv.visitor.user.get_full_name pv.visitor.user %} involving {{ page_url }}">{% firstof pv.visitor.user.get_full_name pv.visitor.user %}</a></td>
<td><a href="{% url 'tracking-visitor-page-detail' user_id=pv.visitor.user.pk %}?page_url={{ page_url }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}" title="View visits by {% firstof pv.visitor.user.get_full_name pv.visitor.user %} involving {{ page_url }}">{{ pv.method }}</a></td>
<td><a href="{% url 'tracking-visitor-page-detail' user_id=pv.visitor.user.pk %}?page_url={{ page_url }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}" title="View visits by {% firstof pv.visitor.user.get_full_name pv.visitor.user %} involving {{ page_url }}">{{ page_url }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% if pageviews.has_previous %}
<a href="{% url 'tracking-page-detail' %}?page_url={{ page_url }}&page={{ pageviews.previous_page_number }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}">previous</a>
{% endif %}
{% if pageviews.has_next %}
<a href="{% url 'tracking-page-detail' %}?page_url={{ page_url }}&page={{ pageviews.next_page_number }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}">next</a>
{% endif %}
</div>
</body>
</html>
45 changes: 45 additions & 0 deletions tracking/templates/tracking/page_overview.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<title>Page Overview - django-tracking2</title>
</head>
<body>
<h1>Page Overview - django-tracking2</h1>
{% include "tracking/snippets/tracking_filters.html" %}
<div id="tracking-stats">
<dl>
<dt>Total Page Views</dt>
<dd>{{ total_page_views }}</dt>
<dt># of Pages Viewed</dt>
<dd>{{ total_pages }}</dt>
</dl>
{% if pageview_counts.has_previous %}
<a href="{% url 'tracking-page-overview' %}?page={{ pageview_counts.previous_page_number }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}">previous</a>
{% endif %}
{% if pageview_counts.has_next %}
<a href="{% url 'tracking-page-overview' %}?page={{ pageview_counts.next_page_number }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}">next</a>
{% endif %}
<table>
<caption>Pages</caption>
<thead>
<th>URL</th>
<th># of Views</th>
</thead>
<tbody>
{% for c in pageview_counts %}
<tr>
<td><a href="{% url 'tracking-page-detail' %}?page_url={{ c.url }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}" title="View all pageviews of {{ c.url }}">{{ c.url }}</a></td>
<td><a href="{% url 'tracking-page-detail' %}?page_url={{ c.url }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}" title="View all pageviews of {{ c.url }}">{{ c.views }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% if pageview_counts.has_previous %}
<a href="{% url 'tracking-page-overview' %}?page={{ pageview_counts.previous_page_number }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}">previous</a>
{% endif %}
{% if pageview_counts.has_next %}
<a href="{% url 'tracking-page-overview' %}?page={{ pageview_counts.next_page_number }}&start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}">next</a>
{% endif %}
</div>
</body>
</html>
4 changes: 3 additions & 1 deletion tracking/templates/tracking/snippets/stats.html
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,17 @@ <h2>Registered Users</h2>
<th># Visits</th>
<th>Avg. Time on Site</th>
<th>Avg. Pages/Visit</th>
<th>Last Pageview</th>
</tr>
</thead>
<tbody>
{% for user in user_stats %}
<tr>
<th>{% firstof user.get_full_name user %}</th>
<th><a href="{% url 'tracking-visitor-overview' user_id=user.pk %}?start={{ start_time|date:"Y-m-d H:i:s" }}&end={{ end_time|date:"Y-m-d H:i:s" }}" title="Click to view visits by {% firstof user.get_full_name user %}">{% firstof user.get_full_name user %}</a></th>
<td>{{ user.visit_count }}</td>
<td>{{ user.time_on_site|default_if_none:"n/a" }}</td>
<td>{{ user.pages_per_visit|floatformat|default:"n/a" }}</td>
<td>{{ user.last_pageview|default:"n/a" }}</td>
</tr>
{% endfor %}
</tbody>
Expand Down
21 changes: 21 additions & 0 deletions tracking/templates/tracking/snippets/tracking_filters.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div id="tracking-filters">
<form method="GET">
{{ form.as_table }}
{% if page_url %}
<input name="page_url" type="hidden" value={{ page_url }} />
{% endif %}
<input type="submit" name="submit" value="submit" />
</form>
</div>
<div id="tracking-info">
<p>
Visitor tracking began on
{{ track_start_time|date:"Y-m-d H:i:s" }}
</p>
{% if warn_incomplete %}
<p class=warning>
The start time precedes the oldest tracked visitor, thus
the stats are not complete for the specified range.
</p>
{% endif %}
</div>
86 changes: 86 additions & 0 deletions tracking/templates/tracking/visitor_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html>
<head>
<title>{% firstof visit.user.get_full_name visit.user %} {{ visit.start_time|date:"Y-m-d H:i:s" }} - {{ visit.end_time|date:"Y-m-d H:i:s" }} Visit Detail - django-tracking2</title>
</head>
<body>
<h1>{% firstof visit.user.get_full_name visit.user %} {{ visit.start_time|date:"Y-m-d H:i:s" }} - {{ visit.end_time|date:"Y-m-d H:i:s" }} Visit Detail - django-tracking2</h1>
<div id="tracking-stats">
<dl>
<dt>Duration</dt>
<dd>{{ visit.time_on_site }}</dt>
<dt># of Page Views</dt>
<dd>{{ pvcount|default:"n/a" }}</dt>
<dt>Avg Time/Page</dt>
<dd>{{ avg_time_per_page|default_if_none:"n/a" }}</dt>
<dt>IP</dt>
<dd>{{ visit.ip_address }}</dt>
<dt>User Agent</dt>
<dd>{{ visit.user_agent }}</dt>
</dl>
{% if pvcount %}
<div id="tracking2-views-per-page">
{% if pageview_stats.has_previous %}
<a href={% url 'tracking-visitor-detail' visit_id=visit.pk %}?pvpage={{ pageviews.number }}&pvspage={{ pageview_stats.previous_page_number }}>previous</a>
{% endif %}
{% if pageview_stats.has_next %}
<a href={% url 'tracking-visitor-detail' visit_id=visit.pk %}?pvpage={{ pageviews.number }}&pvspage={{ pageview_stats.next_page_number }}>next</a>
{% endif %}
<table>
<caption>Views/Page</caption>
<thead>
<th>URL</th>
<th># of views</th>
</thead>
<tbody>
{% for stat in pageview_stats %}
<tr>
<td><a href={% url 'tracking-visitor-page-detail' user_id=visit.user.pk %}?page_url={{ stat.url }} title="View visits by {% firstof visit.user.get_full_name visit.user %} involving {{ stat.url }}">{{ stat.url }}</a></td>
<td>{{ stat.views }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if pageview_stats.has_previous %}
<a href={% url 'tracking-visitor-detail' visit_id=visit.pk %}?pvpage={{ pageviews.number }}&pvspage={{ pageview_stats.previous_page_number }}>previous</a>
{% endif %}
{% if pageview_stats.has_next %}
<a href={% url 'tracking-visitor-detail' visit_id=visit.pk %}?pvpage={{ pageviews.number }}&pvspage={{ pageview_stats.next_page_number }}>next</a>
{% endif %}
</div>

<div id="tracking2-visitor-pageviews">
{% if pageviews.has_previous %}
<a href={% url 'tracking-visitor-detail' visit_id=visit.pk %}?pvpage={{ pageviews.previous_page_number }}&pvspage={{ pageview_stats.number }}>previous</a>
{% endif %}
{% if pageviews.has_next %}
<a href={% url 'tracking-visitor-detail' visit_id=visit.pk %}?pvpage={{ pageviews.next_page_number }}&pvspage={{ pageview_stats.number }}>next</a>
{% endif %}
<table>
<caption>Page Views</caption>
<thead>
<th>Time</th>
<th>Method</th>
<th>URL</th>
</thead>
<tbody>
{% for view in pageviews %}
<tr>
<td>{{ view.view_time|date:"Y-m-d H:i:s" }}</td>
<td>{{ view.method }}</td>
<td><a href={% url 'tracking-pageview-detail' user_id=visit.user.pk pageview_id=view.pk %} title="View pageview details">{{ view.url }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% if pageviews.has_previous %}
<a href={% url 'tracking-visitor-detail' visit_id=visit.pk %}?pvpage={{ pageviews.previous_page_number }}&pvspage={{ pageview_stats.number }}>previous</a>
{% endif %}
{% if pageviews.has_next %}
<a href={% url 'tracking-visitor-detail' visit_id=visit.pk %}?pvpage={{ pageviews.next_page_number }}&pvspage={{ pageview_stats.number }}>next</a>
{% endif %}
</div>
{% endif %}
</div>
</body>
</html>
Loading