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

django 1.9 fixes #23

Open
wants to merge 76 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
45d39a6
Resolved problem with circ dep (app_directories.Loader)
Aug 22, 2011
5c090eb
Added south migrations
Aug 22, 2011
69ab8d2
added visitor to admin interface to capture IPs for banning
svetlyak40wt Apr 21, 2012
41488a5
added visitor to admin interface to capture IPs for banning
jmichelsen Apr 21, 2012
5af4a51
Merge branch 'master' of github.com:jmichelsen/django-tracking
jmichelsen Apr 21, 2012
2f9cfe9
Added support for Django 1.4+ time-zone-aware datetimes by using djan…
jspiros Sep 19, 2012
f700d74
Merge branch 'develop'
jspiros Sep 19, 2012
a292a37
settings.AUTH_USER_MODEL
Oct 27, 2012
3e21cf1
hardcode tracking version
Oct 28, 2012
fbec0f9
listeners depends on Django which isn't installed for in fres environ…
nkeilar Jun 3, 2013
1fe2340
Make compatible with Django 1.6
Nov 6, 2013
e140fb2
Port compatibility fix for Django 1.5
Nov 6, 2013
10a593f
Make compatible with latest Django
Nov 6, 2013
1f56494
update changes
Nov 6, 2013
88865bb
gitignore
Jan 24, 2014
d69833a
don't need this import
Jan 24, 2014
9444460
HAS_GEOIP doesn't seem to exist anymore
Jan 24, 2014
092c42a
Fixed Django 1.6 error: cannot import name HAS_GEOIP
Jun 30, 2014
177a469
Fixed TypeError: can't compare offset-naive and offset-aware datetimes
Jun 30, 2014
57058d9
Update urls.py
Jul 15, 2014
dd3a666
catch Integrity exception added
jlachowski Jul 23, 2014
f22e5df
missing import added
jlachowski Jul 23, 2014
bf247a2
rollback & safe point added
jlachowski Jul 23, 2014
5fbb3c6
pip install update
jlachowski Aug 12, 2014
af14719
version bump
jlachowski Aug 12, 2014
b7b4793
packet name change
jlachowski Aug 12, 2014
693d5ca
Merge branch 'master' of github.com:jlachowski/django-tracking
jlachowski Aug 12, 2014
63129a5
merged with 0.4.1 version from bitbucket
ramusus Feb 26, 2015
1697b56
Fixing the issue with timezone aware timestamps
glossarytingtun Apr 22, 2015
27345aa
Fixing tracking pkg dependency error
glossarytingtun Apr 22, 2015
784fd7b
version.py for versioning
glossarytingtun Apr 22, 2015
f16b009
``get_query_set`` is now ``get_queryset``
bkeating May 5, 2015
4e8d0dd
``IPAddressField`` is now ``GenericIPAddressField``
bkeating May 5, 2015
8c9dda7
Removed rogue character
Jul 20, 2015
89a2116
add badges
bashu Aug 5, 2015
d35992b
update LICENSE
bashu Aug 5, 2015
1114456
cleanup README
bashu Aug 5, 2015
daaec80
add .gitignore
bashu Aug 5, 2015
b03fa8d
update setup.py
bashu Aug 5, 2015
95bf908
Update README.rst
bashu Aug 5, 2015
fe7aa16
Create .landscape.yaml
bashu Aug 6, 2015
7615faa
Update .landscape.yaml
bashu Aug 6, 2015
0dfd499
Update README.rst
bashu Aug 6, 2015
365f219
Update tracking/middleware.py
Sep 16, 2012
a31bb26
Merge branch 'ghost-master' into develop
bashu Sep 18, 2015
c6acc8f
Merge branch 'develop' of https://github.com/bashu/django-tracking in…
bashu Sep 18, 2015
4b92fec
resolving conflicts
bashu Sep 18, 2015
2ee1ca3
Merge branch 'jspiros-master' into develop
bashu Sep 18, 2015
afe912a
resolving conflicts
bashu Sep 18, 2015
da03464
Merge branch 'klichukb-master' into develop
bashu Sep 18, 2015
c9ee4a9
Merge branch 'master' of https://github.com/jmichelsen/django-trackin…
bashu Sep 19, 2015
f3c3e3c
Merge branch 'jmichelsen-master' into develop
bashu Sep 19, 2015
0a1e52b
resolving conflicts
bashu Sep 19, 2015
ddcd83f
Merge branch 'commoncode-master' into develop
bashu Sep 19, 2015
374c401
Merge branch 'master' of https://github.com/madteckhead/django-tracki…
bashu Sep 19, 2015
5a21f20
Merge branch 'madteckhead-master' into develop
bashu Sep 19, 2015
ee85014
resolving conflicts
bashu Sep 19, 2015
05c7a2b
Merge branch 'MontmereLimited-master' into develop
bashu Sep 19, 2015
272c6c4
resolving conflicts
bashu Sep 19, 2015
0b9e29a
Merge branch 'stewiegaribaldi-master' into develop
bashu Sep 19, 2015
27b2280
resolving conflicts
bashu Sep 19, 2015
0200fb3
Merge branch 'ramusus-master' into develop
bashu Sep 19, 2015
f39c518
resolving conflicts
bashu Sep 19, 2015
78be201
Merge branch 'pythonhacker-master' into develop
bashu Sep 19, 2015
b84f90b
resolving conflicts
bashu Sep 19, 2015
09a7474
Merge branch 'pcraston-master' into develop
bashu Sep 19, 2015
82f7095
resolving conflicts
bashu Sep 19, 2015
aec31a9
Merge branch 'bkeating-master' into develop
bashu Sep 19, 2015
f6883f8
Update .landscape.yaml
bashu Sep 24, 2015
d843ba6
django 1.9 fixes
theromis Dec 16, 2015
ec42d3e
fix for multibyte
theromis Dec 16, 2015
9140ff4
fix for right base
theromis Dec 16, 2015
47fd398
user name can not exist
theromis Dec 23, 2015
b806b92
django 1.10 fix
theromis May 18, 2016
ac2f2e8
ipv6 fix
theromis May 8, 2017
4a466bc
version
May 9, 2017
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
53 changes: 53 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml

# Translations
*.pot

# Django stuff:
*.log

# Sphinx documentation
docs/_build/

# PyBuilder
target/
4 changes: 4 additions & 0 deletions .landscape.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ignore-paths:
- south_migrations
- migrations
- example
13 changes: 8 additions & 5 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
Copyright (c) 2008-2009 Josh VanderLinden
The MIT License (MIT)

Copyright (c) 2008-2015 Josh VanderLinden
Copyright (c) 2015 Basil Shubin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -7,13 +10,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
45 changes: 28 additions & 17 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
``django-tracking`` is a simple attempt at keeping track of visitors to
Django-powered Web sites. It also offers basic blacklisting capabilities.
``django-tracking`` is a simple attempt at keeping track of visitors
to django-powered Web sites. It also offers basic blacklisting
capabilities.

The offial repository for ``django-tracking`` is at
http://bitbucket.org/codekoala/django-tracking. Please file any tickets there.
Authored by `Josh VanderLinden <http://www.codekoala.com//>`_, and some great
`contributors <https://github.com/codekoala/django-tracking/contributors>`_.

.. image:: https://img.shields.io/pypi/v/django-tracking.svg
:target: https://pypi.python.org/pypi/django-tracking/

.. image:: https://img.shields.io/pypi/dm/django-tracking.svg
:target: https://pypi.python.org/pypi/django-tracking/

.. image:: https://img.shields.io/github/license/bashu/django-tracking.svg
:target: https://pypi.python.org/pypi/django-tracking/

.. image:: https://landscape.io/github/bashu/django-tracking/develop/landscape.svg?style=flat
:target: https://landscape.io/github/bashu/django-tracking/develop

Features
========
--------

* Tracks the following information about your visitors:

* Session key
* IP address
* User agent
* Whether or not they are a registered user and logged in
* Where they came from (http-referer)
* What page on your site they last visited
* How many pages on your site they have visited
* Session key
* IP address
* User agent
* Whether or not they are a registered user and logged in
* Where they came from (HTTP-REFERER)
* What page on your site they last visited
* How many pages on your site they have visited

* Allows user-agent filtering for visitor tracking
* Automatic clean-up of old visitor records
Expand All @@ -24,8 +37,8 @@ Features
* The ability to have a live feed of active users on your website
* Template tags to:

* display how many active users there are on your site
* determine how many active users are on the same page within your site
* display how many active users there are on your site
* determine how many active users are on the same page within your site

* Optional "Active Visitors Map" to see where visitors are in the world

Expand Down Expand Up @@ -200,7 +213,7 @@ If you also want to show how many people are looking at the same page::
{% visitors_on_page as same_page %}
<p>
{{ same_page }} of {{ visitors }} active user{{ visitors|pluralize }}
{{ same_page|pluralize:"is,are" }} reading this page
{% ifequal same_page 1 %}is{% else %}are{% endifequal %} reading this page
</p>

If you don't want particular areas of your site to be tracked, you may define a
Expand All @@ -223,5 +236,3 @@ default. If you would like to override that setting, set
``TRACKING_CLEANUP_TIMEOUT`` to however many hours you want in your
``settings.py``.

Good luck! Please contact me with any questions or concerns you have with the
project!
34 changes: 21 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
from setuptools import setup, find_packages
import sys, os
import tracking

README = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()

# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))

from tracking import __version__

setup(
name='django-tracking',
version=tracking.get_version(),
version=__version__,
packages=find_packages(exclude=['example']),
include_package_data=True,
license='MIT License',
description="Basic visitor tracking and blacklisting for Django",
long_description=open('README.rst', 'r').read(),
long_description=README,
keywords='django, tracking, visitors',
url='http://github.com/bashu/django-tracking/',
author='Josh VanderLinden',
author_email='codekoala at gmail dot com',
url='http://bitbucket.org/codekoala/django-tracking',
license='MIT',
package_dir={'tracking': 'tracking'},
include_package_data=True,
packages=find_packages(),
author_email='codekoala@gmail.com',
maintainer='Basil Shubin',
maintainer_email='[email protected]',
install_requires=[
'django>=1.4',
],
classifiers=[
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
Expand All @@ -30,6 +37,7 @@
"Operating System :: OS Independent",
"Programming Language :: Python",
"Topic :: Internet :: Log Analysis",
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
"Topic :: Internet :: WWW/HTTP :: Dynamic Content :: Page Counters",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware",
"Topic :: Security",
Expand Down
8 changes: 2 additions & 6 deletions tracking/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import listeners
VERSION = (0, 4, 2)

VERSION = (0, 4, 0)

def get_version():
"Returns the version as a human-format string."
return '.'.join([str(i) for i in VERSION])
__version__ = '.'.join([str(n) for n in VERSION])

7 changes: 5 additions & 2 deletions tracking/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from django.contrib import admin
from tracking.models import BannedIP, UntrackedUserAgent
from tracking.models import Visitor, VisitorManager, BannedIP, UntrackedUserAgent

class VisitorAdmin(admin.ModelAdmin):
search_fields = ['ip_address']
admin.site.register(Visitor, VisitorAdmin)
admin.site.register(BannedIP)
admin.site.register(UntrackedUserAgent)
admin.site.register(UntrackedUserAgent)
11 changes: 10 additions & 1 deletion tracking/listeners.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,21 @@

log = logging.getLogger('tracking.listeners')

importing_exceptions = (ImportError, )
#Try to have the ImproperlyConfigured error available to catch that error during package installation
#...looks like newer versions of Django might have broken only receiving an ImportError
try:
from django.core.exceptions import ImproperlyConfigured
importing_exceptions = (ImportError, ImproperlyConfigured)
except ImportError:
pass

try:
from django.core.cache import cache
from django.db.models.signals import post_save, post_delete

from tracking.models import UntrackedUserAgent, BannedIP
except ImportError:
except importing_exceptions:
pass
else:

Expand Down
34 changes: 17 additions & 17 deletions tracking/middleware.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import datetime, timedelta
from datetime import timedelta
from django.utils import timezone
import logging
import re
import traceback
Expand All @@ -7,15 +8,17 @@
from django.contrib.auth.models import AnonymousUser
from django.core.cache import cache
from django.core.urlresolvers import reverse, NoReverseMatch
from django.db.utils import DatabaseError
from django.db.utils import DatabaseError, IntegrityError
from django.http import Http404
from django.db import transaction

from tracking import utils
from tracking.models import Visitor, UntrackedUserAgent, BannedIP

title_re = re.compile('<title>(.*?)</title>')
log = logging.getLogger('tracking.middleware')


class VisitorTrackingMiddleware(object):
"""
Keeps track of your active users. Anytime a visitor accesses a valid URL,
Expand Down Expand Up @@ -55,9 +58,6 @@ def prefixes(self):
return self._prefixes

def process_request(self, request):
# don't process AJAX requests
if request.is_ajax(): return

# create some useful variables
ip_address = utils.get_ip(request)
user_agent = unicode(request.META.get('HTTP_USER_AGENT', '')[:255], errors='ignore')
Expand All @@ -77,13 +77,9 @@ def process_request(self, request):
log.debug('Not tracking UA "%s" because of keyword: %s' % (user_agent, ua.keyword))
return

if hasattr(request, 'session') and request.session.session_key:
# use the current session key if we can
session_key = request.session.session_key
else:
# otherwise just fake a session key
session_key = '%s:%s' % (ip_address, user_agent)
session_key = session_key[:40]
if not request.session.session_key:
request.session.save()
session_key = request.session.session_key

# ensure that the request.path does not begin with any of the prefixes
for prefix in self.prefixes:
Expand All @@ -93,7 +89,7 @@ def process_request(self, request):

# if we get here, the URL needs to be tracked
# determine what time it is
now = datetime.now()
now=timezone.localtime(timezone.now())

attrs = {
'session_key': session_key,
Expand All @@ -118,9 +114,9 @@ def process_request(self, request):
visitor.session_key = session_key
log.debug('Using existing visitor for IP %s / UA %s: %s' % (ip_address, user_agent, visitor.id))
else:
# it's probably safe to assume that the visitor is brand new
visitor = Visitor(**attrs)
log.debug('Created a new visitor: %s' % attrs)
visitor, created = Visitor.objects.get_or_create(**attrs)
if created:
log.debug('Created a new visitor: %s' % attrs)
except:
return

Expand All @@ -147,7 +143,11 @@ def process_request(self, request):
visitor.page_views += 1
visitor.last_update = now
try:
sid = transaction.savepoint()
visitor.save()
transaction.savepoint_commit(sid)
except IntegrityError:
transaction.savepoint_rollback(sid)
except DatabaseError:
log.error('There was a problem saving visitor information:\n%s\n\n%s' % (traceback.format_exc(), locals()))

Expand All @@ -159,7 +159,7 @@ def process_request(self, request):

if str(timeout).isdigit():
log.debug('Cleaning up visitors older than %s hours' % timeout)
timeout = datetime.now() - timedelta(hours=int(timeout))
timeout = timezone.localtime(timezone.now()) - timedelta(hours=int(timeout))
Visitor.objects.filter(last_update__lte=timeout).delete()

class BannedIPMiddleware:
Expand Down
Loading