ken cochrane avatar ken cochrane committed 6409bf3

adding initial files

Comments (0)

Files changed (12)

+syntax: glob
+*.pyc
+dist
+MANIFEST
+_build
+_static
+.DS_Store
+Requirements
+------------
+Django 1.1 or newer
+Django sessions need to be enabled
+
+
+------------------
+Settings
+------------------
+
+Custom Settings
+===============
+Add the following two properties to your settings file
+
+# COOKIE_DOMAIN
+# Default = None, Which means local domain only  www.domain.com but no funky.domain.com
+# if you want cookie to work across all subdomains, put '.domain.com' 
+COOKIE_DOMAIN = None # .domain.com
+
+# COOKE_MAX_AGE
+# Default = 31536000 or 1 year.
+# This is how long the cookie will live in your visitors browser before it expires on it's own
+COOKIE_MAX_AGE = 31536000 # 1 year
+
+
+Middleware 
+==========
+Add 'visitor.middleware.visitor_middleware.VisitorMiddleware' to your MIDDLEWARE_CLASSES settings
+
+
+App
+===
+Add visitor to INSTALLED_APPS
+
+
+Views and templates
+===================
+There are none, this is strictly a model based app.
+
+
+Sync Tables
+===========
+Run ./manage.py syncdb to load up the tables in your database.
+Copyright (c) 2010, Ken Cochrane
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of the author nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+========================
+Django visitor
+========================
+
+This is a fairly simple visitor tracking application for Django,
+designed to make allowing tracking visitors as painless as possible. It
+requires a functional installation of Django 1.1 or newer, but has no
+other dependencies.
+
+For installation instructions, see the file "INSTALL" in this
+directory;

Empty file added.

+from django.contrib import admin
+from visitor.models import Visitor
+
+class VisitorAdmin(admin.ModelAdmin):
+    list_display = ['visitor_key', 'num_visits', 'last_update', 'created']
+
+admin.site.register(Visitor, VisitorAdmin)

visitor/managers.py

+from django.db import models
+
+#===============================================================================
+class VisitorManager(models.Manager):
+    
+    #---------------------------------------------------------------------------
+    def find_visitor(self, visitor_key):
+        try:
+            return self.get(visitor_key=visitor_key)
+        except self.model.DoesNotExist:
+            print("model doesn't exist")
+            return None
+            
+    #---------------------------------------------------------------------------
+    def create_from_ip(self, ip):
+        from visitor.visitor_utils import create_uuid
+        return self.get_or_create(visitor_key=create_uuid(ip))[0]
+        
Add a comment to this file

visitor/middleware/__init__.py

Empty file added.

visitor/middleware/visitor_middleware.py

+"""
+Visitor's Middleware, it will look to see if we already registered this visitor
+if not, it will create a cookie, and create a visitor record for future tracking. 
+If we already know about them we get their visitor record and update it.
+"""
+from django import http
+
+from visitor.visitor_utils import *
+from visitor import visitor_constants as constants
+
+
+#===============================================================================
+class VisitorMiddleware(object):
+    """ 
+    Visitors middleware it will look to see if we already registered this 
+    visitor if not, it will create a cookie, and create a visitor record for 
+    future tracking. If we already know about them we get their visitor record 
+    and update it.
+    """
+
+    #--------------------------------------------------------------------------
+    def process_request(self, request):
+        """ get or set the visitor cookie """
+        # figure out the IP
+        ip_address = ip_address_from_request(request) or 'Unknown'
+
+        # we check to see if they have a cookie, if they do we update the stats
+        # for the cookie if they don't have a cookie, we create the cookie.
+        # then we associate that cookie to the web request 
+        # later on in the response if we haven't set the cookie yet, we will 
+        # set the cookie in the browser.
+        
+        cookie_saved = request.session.get(constants.COOKIE_SAVED, None)
+        visitor_key = request.session.get(constants.VISITOR_KEY, None)
+        visitor_key_cookie = get_vistor_cookie_key(request)
+        
+        # print("cookie saved = %s" % cookie_saved)
+        # print("visitor_key = %s" % visitor_key)
+        # print("visitor_key_cookie = %s" % visitor_key_cookie)
+        
+        # if we have a visitor key, and cookie_saved from session
+        # and we get a cookie and the cookie's visitor key matches the one 
+        # in the session then we don't need to continue, everything is all
+        # set.
+        #
+        # if we wanted to update the visitor every time they made a request
+        # we wouldn't do this, but that would take a lot of resources for
+        # large sites, so we will defer that to a future version for now.
+        if (visitor_key and 
+            cookie_saved and 
+            visitor_key_cookie and 
+            visitor_key == visitor_key_cookie):
+                return None
+        
+        session_key = request.session.session_key
+        # print("session_key = %s" % session_key)
+        
+        if visitor_key_cookie:
+            request.session[constants.COOKIE_SAVED] = True
+            visitor = update_visitor(visitor_key_cookie, 
+                                     session_key=session_key)
+                                     
+            if not visitor:
+                # we couldn't find their old cookie, so create a new one.
+                request.session[constants.COOKIE_SAVED] = False
+                visitor = create_visitor(ip_address, session_key)
+                                         
+        else:
+            request.session[constants.COOKIE_SAVED] = False
+            visitor = create_visitor(ip_address, session_key)
+
+        request.session[constants.VISITOR_KEY] = visitor.visitor_key
+        return None
+
+    #--------------------------------------------------------------------------
+    def process_response(self,request, response):
+        """ look if we need to save the visitor cookie """
+        if hasattr(request, 'session'):
+            cookie_saved = request.session.get(constants.COOKIE_SAVED, None)
+            visitor_key = request.session.get(constants.VISITOR_KEY, None)
+            if not cookie_saved and visitor_key:
+                set_visitor_cookie_from_key(response, visitor_key)
+                request.session[constants.COOKIE_SAVED] = True
+        return response

visitor/models.py

+from django.db import models
+from django.contrib.sessions.models import Session
+from django.conf import settings
+from django.contrib.auth import SESSION_KEY, BACKEND_SESSION_KEY, load_backend
+from django.contrib.auth.models import AnonymousUser
+
+from visitor import managers
+
+from datetime import datetime
+
+#==============================================================================
+class Visitor(models.Model):
+    visitor_key = models.CharField(max_length='50')
+    created = models.DateTimeField(default=datetime.now())
+    last_update = models.DateTimeField()
+    num_visits = models.SmallIntegerField(default=0)
+    last_session_key = models.CharField(max_length=40)
+    
+    objects = managers.VisitorManager()
+    
+    #---------------------------------------------------------------------------
+    def __unicode__(self):
+        return '#%d/%s' % (self.id, self.last_session_key)
+        
+    #--------------------------------------------------------------------------
+    def generate_key(self, ip_address):
+        if not self.visitor_key:
+            from visitor.visitor_utils import create_uuid
+            self.visitor_key = create_uuid(ip_address)
+        return self.visitor_key
+
+    #--------------------------------------------------------------------------
+    def mark_visit(self):
+        self.num_visits += 1
+
+    #--------------------------------------------------------------------------
+    def save(self, *args, **kws):
+        self.last_update = datetime.now()
+        super(Visitor, self).save(*args, **kws)
+        
+    #--------------------------------------------------------------------------
+    @property
+    def session(self):
+        try:
+            return Session.objects.get(session_key=self.last_session_key)
+        except Session.DoesNotExist:
+            return None
+            
+    #--------------------------------------------------------------------------
+    @property      
+    def user():
+        """ 
+            a backend-agnostic way to get the user from the session.
+            
+            Originally taken from http://djangosnippets.org/snippets/1276/ and
+            changed a little. Thanks jdunck
+            
+        """
+        session_engine = __import__(settings.SESSION_ENGINE, {}, {}, [''])
+        session_wrapper = session_engine.SessionStore(self.last_session_key)
+        user_id = session_wrapper.get(SESSION_KEY)
+        auth_backend = load_backend(session_wrapper.get(BACKEND_SESSION_KEY))
+
+        if user_id and auth_backend:
+          return auth_backend.get_user(user_id)
+        else:
+          return AnonymousUser()
+    

visitor/visitor_constants.py

+VISITOR_KEY = 'visitor_key'
+COOKIE_SAVED = 'cookie_saved'
+COOKIE_VISITOR_KEY = 'vk'

visitor/visitor_utils.py

+import uuid
+import time
+import itertools
+
+from visitor.models import Visitor
+from visitor import visitor_constants as constants
+from django.conf import settings
+
+# this is a counter to make sure our uuid's are unique.
+counter = itertools.count(0).next
+
+# pull settings from settings file, if not there, use reasonable defaults
+COOKIE_DOMAIN = getattr(settings, 'COOKIE_DOMAIN', None) # local domain only 
+COOKIE_MAX_AGE = getattr(settings, 'COOKIE_MAX_AGE', 31536000) # 1 year
+
+#-------------------------------------------------------------------------------
+def create_uuid(*parts):
+    name = '-'.join([str(counter())] + [str(time.time())] + [str(p) for p in parts])
+    return str(uuid.uuid5(uuid.NAMESPACE_URL, name))
+    
+#-------------------------------------------------------------------------------
+def ip_address_from_request(request):
+    meta = request.META
+
+  # figure out the IP
+    if 'REMOTE_ADDR' in meta and meta.get('REMOTE_ADDR', '') != '127.0.0.1':
+        ip_address = meta.get('REMOTE_ADDR', '')
+    elif 'HTTP_X_REAL_IP' in meta:
+        ip_address = meta.get('HTTP_X_REAL_IP', '')
+    elif 'HTTP_X_FORWARDED_FOR' in meta:
+        ip_address = meta.get('HTTP_X_FORWARDED_FOR', '')
+    else:
+        ip_address = meta.get('REMOTE_ADDR', None)
+
+    return ip_address
+    
+#-------------------------------------------------------------------------------
+def get_visitor(visitor_key):
+    """ get the visitor using the visitor key """
+    return Visitor.objects.find_visitor(visitor_key)
+
+#-------------------------------------------------------------------------------
+def create_visitor(ip_address,session_key):
+    """ Create the visitor given an ip_address """
+    visitor = Visitor()
+    visitor.generate_key(ip_address)
+    visitor.mark_visit()
+    visitor.last_session_key = session_key
+    visitor.save()
+    return visitor
+
+#-------------------------------------------------------------------------------
+def update_visitor(visitor_key,session_key=None):
+    """ update the visitor using the visitor key """
+    visitor = Visitor.objects.find_visitor(visitor_key)
+    if visitor:
+        visitor.mark_visit()
+        if session_key:
+            visitor.last_session_key = session_key
+        visitor.save()
+    return visitor
+
+
+#-------------------------------------------------------------------------------
+def get_vistor_cookie_key(request):
+    """ look for the cookie and if we find one return the visitor key """
+    if constants.COOKIE_VISITOR_KEY in request.COOKIES:
+        return request.COOKIES[constants.COOKIE_VISITOR_KEY]
+    else:
+        return None
+        
+#-------------------------------------------------------------------------------
+def get_vistor_from_request(request):
+    """ look for the cookie and if we find one return the visitor key """
+    if constants.COOKIE_VISITOR_KEY in request.COOKIES:
+        return get_visitor(request.COOKIES[constants.COOKIE_VISITOR_KEY])
+    else:
+        return None
+
+
+#-------------------------------------------------------------------------------
+def set_visitor_cookie(response, visitor):
+    """ set the visitor cookie using the visitor object """
+    if response and visitor and visitor.visitor_key:
+        response.set_cookie(
+            constants.COOKIE_VISITOR_KEY, 
+            visitor.visitor_key,
+            max_age=COOKIE_MAX_AGE,
+            domain=COOKIE_DOMAIN
+        )
+
+#-------------------------------------------------------------------------------
+def set_visitor_cookie_from_key(response, visitor_key):
+    """ set the cookie using the visitor_key"""
+    if response and visitor_key:
+        response.set_cookie(
+            constants.COOKIE_VISITOR_KEY, 
+            visitor_key,
+            max_age=COOKIE_MAX_AGE,
+            domain=COOKIE_DOMAIN
+        )
+
+#-------------------------------------------------------------------------------
+def delete_visitor_cookie(response):
+    """ delete the visitor cookie """
+    if response:
+        response.delete_cookie(
+            constants.COOKIE_VISITOR_KEY,
+            domain=COOKIE_DOMAIN
+        )
+
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.