An asynchronous user activity tracking API for Django.
Project description
Djaffar: asynchronous user activity tracking for Django
=======================================================
|Build Status| |PyPI version|
Want to keep track of what your users do even when they don't hit the
server? Set up Djaffar on the server and make a request to the client
API to log user activity to the database, including URI path, user name,
browser session, IP address and user agent.
Requirements
------------
- Django (1.8, 1.9, 1.10)
- Django Rest Framework (3.3, 3.4, 3.5)
Installation
------------
Install with ``pip``:
::
pip install django-djaffar
Add Djaffar to your project (typically in ``settings.py``):
.. code:: python
INSTALLED_APPS = [
...
'djaffar',
]
Specify the URL that will be used to hit Djaffar (typically in
``urls.py``):
.. code:: python
from django.conf.urls import url, include
urlpatterns = [
...
url(r'^djaffar/', include('djaffar.urls')),
]
Make sure the authentication classes you use for your users are
specified in the Django Rest Framework settings (typically in
``settings.py``):
.. code:: python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'path.to.AuthenticationClass',
)
}
Run the database migration:
::
$ python manage.py migrate djaffar
Client API
----------
When sending a POST request to Djaffar to log activity, you should care
about the following properties:
+----------------+------------+-------+---------+----------+--------+
| Property name | Mandatory | Type | Format | Example | Usage |
+================+============+=======+=========+==========+========+
| ``date`` | Yes | Form | ISO | ``2016-1 | Date |
| | | data | 8601 | 2-29T07: | and |
| | | | | 35:22.57 | time |
| | | | | 1Z`` | when |
| | | | | | the |
| | | | | | log |
| | | | | | reques |
| | | | | | t |
| | | | | | is |
| | | | | | initia |
| | | | | | ted. |
+----------------+------------+-------+---------+----------+--------+
| ``path`` | No | Form | - | ``users/ | URL |
| | | data | | me/cart/ | path |
| | | | | `` | taken |
| | | | | | by the |
| | | | | | user. |
| | | | | | If not |
| | | | | | specif |
| | | | | | ied, |
| | | | | | the |
| | | | | | refere |
| | | | | | r |
| | | | | | *from |
| | | | | | the |
| | | | | | reques |
| | | | | | t |
| | | | | | header |
| | | | | | s* |
| | | | | | (not |
| | | | | | the |
| | | | | | ``refe |
| | | | | | rer`` |
| | | | | | form |
| | | | | | data |
| | | | | | proper |
| | | | | | ty) |
| | | | | | will |
| | | | | | be |
| | | | | | used |
| | | | | | in |
| | | | | | place. |
+----------------+------------+-------+---------+----------+--------+
| ``referer`` | No | Form | - | ``https: | URL of |
| | | data | | //www.go | the |
| | | | | ogle.com | page |
| | | | | /`` | the |
| | | | | | user |
| | | | | | comes |
| | | | | | from |
| | | | | | (if |
| | | | | | any). |
+----------------+------------+-------+---------+----------+--------+
Examples
~~~~~~~~
Basic log
^^^^^^^^^
Request Djaffar to log an activity with the current date:
.. code:: javascript
var xhr = new XMLHttpRequest();
xhr.open('POST', '/djaffar/log/', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send('date=' + new Date().toISOString());
URL fragments
^^^^^^^^^^^^^
If your client app relies on URL fragments for navigation, you'll need
to manually set the ``path`` parameter when you hit Djaffar:
.. code:: javascript
...
xhr.send(... + '&path=' + (window.location.href.split('#')[1] || '/'))
User authentication
^^^^^^^^^^^^^^^^^^^
- If you use session-based authentication, the cookie is automatically
set in the request headers by your browser.
- But if you use token-based authentication, you'll need to set the
token in the request headers, like so:
.. code:: javascript
...
xhr.setRequestHeader('Authorization', 'Bearer F2naN20HpDv4tsJC0b1OhQZVDwRiEy');
xhr.send(...)
Retrieving activity logs
------------------------
Logs are stored as instances of the ``Activity`` model (in
``djaffar.models``) and have the following properties:
+-------------------+--------------+-------------------+
| Model field name | Description | Model field type |
+===================+==============+===================+
| ``user`` | Instance of | ``ForeignKey`` |
| | the ``User`` | |
| | model if | |
| | authenticate | |
| | d, | |
| | ``None`` | |
| | otherwise | |
+-------------------+--------------+-------------------+
| ``session`` | User browser | ``ForeignKey`` |
| | session, | |
| | instance of | |
| | the | |
| | ``Session`` | |
| | model | |
+-------------------+--------------+-------------------+
| ``ip_address`` | User IP | ``CharField`` |
+-------------------+--------------+-------------------+
| ``date`` | User | ``DateTimeField`` |
| | activity | |
| | date and | |
| | time | |
+-------------------+--------------+-------------------+
| ``path`` | User | ``CharField`` |
| | activity | |
| | path | |
+-------------------+--------------+-------------------+
| ``referer`` | User | ``CharField`` |
| | activity | |
| | referer | |
+-------------------+--------------+-------------------+
.. figure:: https://trello-attachments.s3.amazonaws.com/5841a8e7863eaf470b1e5d57/585d6cb3d8336749a4162b7f/c6717d6623b04b3f791718c88e9f21a1/Screen_Shot_2016-12-27_at_10.15.08.png
:alt: Accessing logs from the Django shell
Accessing logs from the Django shell
Djaffar also adds the ``SessionInfo`` model, linked to the ``Session``
model through a foreign key, with the following properties:
+--------------------+-------------------------------------+--------------------+
| Model field name | Description | Model field type |
+====================+=====================================+====================+
| ``user_agent`` | User agent of the browser session | ``CharField`` |
+--------------------+-------------------------------------+--------------------+
You can get JSON dumps of the activity logs and the session info with
Django's standard ``dumpdata`` command:
::
python manage.py dumpdata djaffar.Activity --indent=2 > djaffar-activity.json
python manage.py dumpdata djaffar.SessionInfo --indent=2 > djaffar-sessioninfo.json
Appendix
--------
About sessions
~~~~~~~~~~~~~~
Djaffar uses `Django
sessions <https://docs.djangoproject.com/en/1.10/topics/http/sessions/>`__
to keep track of browser sessions when logging user activity. Depending
on settings, sessions either expire when the user closes their browser
or after a given age (see `Browser-length sessions vs. persistent
sessions <https://docs.djangoproject.com/en/1.10/topics/http/sessions/#browser-length-vs-persistent-sessions>`__).
Whether your app uses session-based user authentication or not, Djaffar
uses session (and the associated user agent) for two reasons:
- Allowing you to distinguish between anonymous visitors
- Allowing you to distinguish between visits by the same authenticated
user through various devices
Tests
-----
Run tests (``tests/tests.py``) against the supported versions of Python
and the required packages, as listed in ``tox.ini``:
::
tox
.. |Build Status| image:: https://travis-ci.org/arnaudrenaud/django-djaffar.svg?branch=master
:target: https://travis-ci.org/arnaudrenaud/django-djaffar
.. |PyPI version| image:: https://badge.fury.io/py/django-djaffar.svg
:target: https://badge.fury.io/py/django-djaffar
=======================================================
|Build Status| |PyPI version|
Want to keep track of what your users do even when they don't hit the
server? Set up Djaffar on the server and make a request to the client
API to log user activity to the database, including URI path, user name,
browser session, IP address and user agent.
Requirements
------------
- Django (1.8, 1.9, 1.10)
- Django Rest Framework (3.3, 3.4, 3.5)
Installation
------------
Install with ``pip``:
::
pip install django-djaffar
Add Djaffar to your project (typically in ``settings.py``):
.. code:: python
INSTALLED_APPS = [
...
'djaffar',
]
Specify the URL that will be used to hit Djaffar (typically in
``urls.py``):
.. code:: python
from django.conf.urls import url, include
urlpatterns = [
...
url(r'^djaffar/', include('djaffar.urls')),
]
Make sure the authentication classes you use for your users are
specified in the Django Rest Framework settings (typically in
``settings.py``):
.. code:: python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'path.to.AuthenticationClass',
)
}
Run the database migration:
::
$ python manage.py migrate djaffar
Client API
----------
When sending a POST request to Djaffar to log activity, you should care
about the following properties:
+----------------+------------+-------+---------+----------+--------+
| Property name | Mandatory | Type | Format | Example | Usage |
+================+============+=======+=========+==========+========+
| ``date`` | Yes | Form | ISO | ``2016-1 | Date |
| | | data | 8601 | 2-29T07: | and |
| | | | | 35:22.57 | time |
| | | | | 1Z`` | when |
| | | | | | the |
| | | | | | log |
| | | | | | reques |
| | | | | | t |
| | | | | | is |
| | | | | | initia |
| | | | | | ted. |
+----------------+------------+-------+---------+----------+--------+
| ``path`` | No | Form | - | ``users/ | URL |
| | | data | | me/cart/ | path |
| | | | | `` | taken |
| | | | | | by the |
| | | | | | user. |
| | | | | | If not |
| | | | | | specif |
| | | | | | ied, |
| | | | | | the |
| | | | | | refere |
| | | | | | r |
| | | | | | *from |
| | | | | | the |
| | | | | | reques |
| | | | | | t |
| | | | | | header |
| | | | | | s* |
| | | | | | (not |
| | | | | | the |
| | | | | | ``refe |
| | | | | | rer`` |
| | | | | | form |
| | | | | | data |
| | | | | | proper |
| | | | | | ty) |
| | | | | | will |
| | | | | | be |
| | | | | | used |
| | | | | | in |
| | | | | | place. |
+----------------+------------+-------+---------+----------+--------+
| ``referer`` | No | Form | - | ``https: | URL of |
| | | data | | //www.go | the |
| | | | | ogle.com | page |
| | | | | /`` | the |
| | | | | | user |
| | | | | | comes |
| | | | | | from |
| | | | | | (if |
| | | | | | any). |
+----------------+------------+-------+---------+----------+--------+
Examples
~~~~~~~~
Basic log
^^^^^^^^^
Request Djaffar to log an activity with the current date:
.. code:: javascript
var xhr = new XMLHttpRequest();
xhr.open('POST', '/djaffar/log/', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send('date=' + new Date().toISOString());
URL fragments
^^^^^^^^^^^^^
If your client app relies on URL fragments for navigation, you'll need
to manually set the ``path`` parameter when you hit Djaffar:
.. code:: javascript
...
xhr.send(... + '&path=' + (window.location.href.split('#')[1] || '/'))
User authentication
^^^^^^^^^^^^^^^^^^^
- If you use session-based authentication, the cookie is automatically
set in the request headers by your browser.
- But if you use token-based authentication, you'll need to set the
token in the request headers, like so:
.. code:: javascript
...
xhr.setRequestHeader('Authorization', 'Bearer F2naN20HpDv4tsJC0b1OhQZVDwRiEy');
xhr.send(...)
Retrieving activity logs
------------------------
Logs are stored as instances of the ``Activity`` model (in
``djaffar.models``) and have the following properties:
+-------------------+--------------+-------------------+
| Model field name | Description | Model field type |
+===================+==============+===================+
| ``user`` | Instance of | ``ForeignKey`` |
| | the ``User`` | |
| | model if | |
| | authenticate | |
| | d, | |
| | ``None`` | |
| | otherwise | |
+-------------------+--------------+-------------------+
| ``session`` | User browser | ``ForeignKey`` |
| | session, | |
| | instance of | |
| | the | |
| | ``Session`` | |
| | model | |
+-------------------+--------------+-------------------+
| ``ip_address`` | User IP | ``CharField`` |
+-------------------+--------------+-------------------+
| ``date`` | User | ``DateTimeField`` |
| | activity | |
| | date and | |
| | time | |
+-------------------+--------------+-------------------+
| ``path`` | User | ``CharField`` |
| | activity | |
| | path | |
+-------------------+--------------+-------------------+
| ``referer`` | User | ``CharField`` |
| | activity | |
| | referer | |
+-------------------+--------------+-------------------+
.. figure:: https://trello-attachments.s3.amazonaws.com/5841a8e7863eaf470b1e5d57/585d6cb3d8336749a4162b7f/c6717d6623b04b3f791718c88e9f21a1/Screen_Shot_2016-12-27_at_10.15.08.png
:alt: Accessing logs from the Django shell
Accessing logs from the Django shell
Djaffar also adds the ``SessionInfo`` model, linked to the ``Session``
model through a foreign key, with the following properties:
+--------------------+-------------------------------------+--------------------+
| Model field name | Description | Model field type |
+====================+=====================================+====================+
| ``user_agent`` | User agent of the browser session | ``CharField`` |
+--------------------+-------------------------------------+--------------------+
You can get JSON dumps of the activity logs and the session info with
Django's standard ``dumpdata`` command:
::
python manage.py dumpdata djaffar.Activity --indent=2 > djaffar-activity.json
python manage.py dumpdata djaffar.SessionInfo --indent=2 > djaffar-sessioninfo.json
Appendix
--------
About sessions
~~~~~~~~~~~~~~
Djaffar uses `Django
sessions <https://docs.djangoproject.com/en/1.10/topics/http/sessions/>`__
to keep track of browser sessions when logging user activity. Depending
on settings, sessions either expire when the user closes their browser
or after a given age (see `Browser-length sessions vs. persistent
sessions <https://docs.djangoproject.com/en/1.10/topics/http/sessions/#browser-length-vs-persistent-sessions>`__).
Whether your app uses session-based user authentication or not, Djaffar
uses session (and the associated user agent) for two reasons:
- Allowing you to distinguish between anonymous visitors
- Allowing you to distinguish between visits by the same authenticated
user through various devices
Tests
-----
Run tests (``tests/tests.py``) against the supported versions of Python
and the required packages, as listed in ``tox.ini``:
::
tox
.. |Build Status| image:: https://travis-ci.org/arnaudrenaud/django-djaffar.svg?branch=master
:target: https://travis-ci.org/arnaudrenaud/django-djaffar
.. |PyPI version| image:: https://badge.fury.io/py/django-djaffar.svg
:target: https://badge.fury.io/py/django-djaffar
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
django-djaffar-0.1.10.tar.gz
(7.7 kB
view details)
Built Distribution
File details
Details for the file django-djaffar-0.1.10.tar.gz
.
File metadata
- Download URL: django-djaffar-0.1.10.tar.gz
- Upload date:
- Size: 7.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | afde1e4b813896157d5b6df110f25b21141ba66edd2f1d56f1b94925dc52c3cc |
|
MD5 | 9cadd9ed723064487ab8e8e34b3b02cb |
|
BLAKE2b-256 | 5735fc0a40a9646466196952240c4154c54d5586fd0c739be4347d003dcbeb41 |
File details
Details for the file django_djaffar-0.1.10-py2.py3-none-any.whl
.
File metadata
- Download URL: django_djaffar-0.1.10-py2.py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | fb179bb19addcb6efb3953b0ef9d8502e6a0e79ddd7a1b398464804ce3ce5e0d |
|
MD5 | e56cb8754148649cda9006cd38cc2cf5 |
|
BLAKE2b-256 | 6cf2dd52c0462127faaf5a41936c43e89d8da8337a9b20a9940a03e9936d02b7 |