django-bandits


Namedjango-bandits JSON
Version 0.1.6 PyPI version JSON
download
home_pagehttps://github.com/hubbs5/django-bandits
SummaryA package enabling multi-armed bandits for site optimization and Django.
upload_time2023-09-01 21:04:59
maintainer
docs_urlNone
authorChristian
requires_python>=3.8,<3.13
licenseApache 2.0
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-bandits

This package enables optimization of your Django site via multi-armed bandits.

This package extends [Django-Waffle](https://waffle.readthedocs.io/en/stable/) by wrapping the feature flipper functions with bandit algorithms. This allows automatic testing and optimization as users interact with your site.

## Installation

`pip install django-bandits`

or 

`poetry add django-bandits`

Additionally, you can install it directly from GitHub:

### Pip
`pip install git+https://github.com/hubbs5/django-bandits.git`
### Poetry
`poetry add git+https://github.com/hubbs5/django-bandits.git`

### Django Settings

Go to your `settings.py` file and add `waffle` to your installed apps list:
```
INSTALLED_APPS = [
    ...
    "waffle",
    "django_bandits",
    ...
]
```

Additionally, add `django_bandits.middleware.UserActivityMiddleware` to `MIDDLEWARE` after CSRF and authentication middleware, e.g.:

```
MIDDLEWARE = [
    ...
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django_bandits.middleware.UserActivityMiddleware", # It goes here!
    ...
]
```

Update `settings.py` to exclude any particular URL from conversion tracking, e.g.:
```
EXCLUDE_FROM_TRACKING = [
    ADMIN_URL,
]
```

Additionally, you can add a REGEX option to filter URLs. Helps to ensure you aren't picking up bot traffic that's trying to break into a Wordpress site or something of the sort.
```
EXCLUDE_FROM_TRACKING_REGEX = r"\.php|wordpress|\/wp-"
```

Finally add the following line to your `settings.py` file to ensure the bandit model is overriding Waffle's Flags.
```
WAFFLE_FLAG_MODEL = "django_bandits.BanditFlag"
```

### Migrations

Create migrations by running `python manage.py makemigrations` followed by `python manage.py migrate`.

### Enabling Bandits

With migrations complete, go to the Django site admin page. You should see something like this:

![View of Django admin page](docs/images/django_admin_bandit_1.png)

Select `Flags` under `DJANGO_BANDITS` and click "Add."

Make a name for the flag - typically the feature you want to test. Set it to test for whatever group you'd like to test it on. Refer to the [Waffle documentation](https://waffle.readthedocs.io/en/stable/) for details.

The bandit needs a `FLAG URL` to be set - this is the URL where the flag will be shown to users and is needed to track conversions and call the bandit to flip the feature when users reach that URL. Enter this as the `Source URL`.

To track a conversion, then you need to add a `Target URL`, which is where you want the user to end up.

In the example below, we're tracking the homepage (`/`) and want to see how many users click on a link to go to the contact page (`/contact/`).

![FLAG URL settings determines a successful conversion](docs/images/django_admin_bandit_flag_url.png)

This will consider any user who views your source URL and target URL to be a conversion during the session and will update the count shown in the image above.

To add a bandit, you'll need to select one of the bandit options from the list below:
![Select from Epsilon Greedy, Epsilon Decay, or UCB1 Bandits](docs/images/bandit-selection.png)

Some bandits have customizable parameters (e.g. how frequently a random action is taken such as $\epsilon$). All allow you to set a minimum number of views and confidence interval before a winning version is selected (see more details below).

Now that a bandit is enabled, you need to update your templates or views in as done with Waffle to enable the feature flipping flag.

In a template, it may be something like this:

```
{% extends "base.html" %}
{% load waffle_tags %}

{% block content %}
{% flag "headline-flag" %}
    <h1>This is my test headline: Waffle Flag is <strong>active</strong></h1>
{% else %}
    <h1>This is my base headline: Waffle Flag is <strong>inactive</strong></h1>
{% endflag %}
    <a href="{% url 'ab_test:target' %}">Click here to see the target page</a>
{% endblock %}
```

Where "`headline-flag`" is the name of the flag you defined in the admin page.

### Performance Tracking

The bandits will automatically select a winning option when the given criteria are met. When setting up a bandit, you can select the `SIGNIFICANCE LEVEL`(default is 0.05) and the `MIN VIEWS` (default is 100). 

After the `MIN VIEWS` threshold is reached, the model will perform a two-sided t-test to determine if there's significant difference in the two options (i.e. p-value < `SIGNIFICANCE LEVEL`). If this criteria is met, the bandit will then default to the winning option for all future visits to avoid potential conversion losses from testing.

As a user, you can also view the conversion rate and the upper and lower bounds of the confidence intervals at any time within the admin page.

![A view of the bandit stats](docs/images/bandit-stats.png)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/hubbs5/django-bandits",
    "name": "django-bandits",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<3.13",
    "maintainer_email": "",
    "keywords": "",
    "author": "Christian",
    "author_email": "christiandhubbs@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/f9/bd/75a8c6708851c202a069051221d5cde2f8a9fd02423515e8963e9a02107b/django_bandits-0.1.6.tar.gz",
    "platform": null,
    "description": "# django-bandits\n\nThis package enables optimization of your Django site via multi-armed bandits.\n\nThis package extends [Django-Waffle](https://waffle.readthedocs.io/en/stable/) by wrapping the feature flipper functions with bandit algorithms. This allows automatic testing and optimization as users interact with your site.\n\n## Installation\n\n`pip install django-bandits`\n\nor \n\n`poetry add django-bandits`\n\nAdditionally, you can install it directly from GitHub:\n\n### Pip\n`pip install git+https://github.com/hubbs5/django-bandits.git`\n### Poetry\n`poetry add git+https://github.com/hubbs5/django-bandits.git`\n\n### Django Settings\n\nGo to your `settings.py` file and add `waffle` to your installed apps list:\n```\nINSTALLED_APPS = [\n    ...\n    \"waffle\",\n    \"django_bandits\",\n    ...\n]\n```\n\nAdditionally, add `django_bandits.middleware.UserActivityMiddleware` to `MIDDLEWARE` after CSRF and authentication middleware, e.g.:\n\n```\nMIDDLEWARE = [\n    ...\n    \"django.middleware.common.CommonMiddleware\",\n    \"django.middleware.csrf.CsrfViewMiddleware\",\n    \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n    \"django_bandits.middleware.UserActivityMiddleware\", # It goes here!\n    ...\n]\n```\n\nUpdate `settings.py` to exclude any particular URL from conversion tracking, e.g.:\n```\nEXCLUDE_FROM_TRACKING = [\n    ADMIN_URL,\n]\n```\n\nAdditionally, you can add a REGEX option to filter URLs. Helps to ensure you aren't picking up bot traffic that's trying to break into a Wordpress site or something of the sort.\n```\nEXCLUDE_FROM_TRACKING_REGEX = r\"\\.php|wordpress|\\/wp-\"\n```\n\nFinally add the following line to your `settings.py` file to ensure the bandit model is overriding Waffle's Flags.\n```\nWAFFLE_FLAG_MODEL = \"django_bandits.BanditFlag\"\n```\n\n### Migrations\n\nCreate migrations by running `python manage.py makemigrations` followed by `python manage.py migrate`.\n\n### Enabling Bandits\n\nWith migrations complete, go to the Django site admin page. You should see something like this:\n\n![View of Django admin page](docs/images/django_admin_bandit_1.png)\n\nSelect `Flags` under `DJANGO_BANDITS` and click \"Add.\"\n\nMake a name for the flag - typically the feature you want to test. Set it to test for whatever group you'd like to test it on. Refer to the [Waffle documentation](https://waffle.readthedocs.io/en/stable/) for details.\n\nThe bandit needs a `FLAG URL` to be set - this is the URL where the flag will be shown to users and is needed to track conversions and call the bandit to flip the feature when users reach that URL. Enter this as the `Source URL`.\n\nTo track a conversion, then you need to add a `Target URL`, which is where you want the user to end up.\n\nIn the example below, we're tracking the homepage (`/`) and want to see how many users click on a link to go to the contact page (`/contact/`).\n\n![FLAG URL settings determines a successful conversion](docs/images/django_admin_bandit_flag_url.png)\n\nThis will consider any user who views your source URL and target URL to be a conversion during the session and will update the count shown in the image above.\n\nTo add a bandit, you'll need to select one of the bandit options from the list below:\n![Select from Epsilon Greedy, Epsilon Decay, or UCB1 Bandits](docs/images/bandit-selection.png)\n\nSome bandits have customizable parameters (e.g. how frequently a random action is taken such as $\\epsilon$). All allow you to set a minimum number of views and confidence interval before a winning version is selected (see more details below).\n\nNow that a bandit is enabled, you need to update your templates or views in as done with Waffle to enable the feature flipping flag.\n\nIn a template, it may be something like this:\n\n```\n{% extends \"base.html\" %}\n{% load waffle_tags %}\n\n{% block content %}\n{% flag \"headline-flag\" %}\n    <h1>This is my test headline: Waffle Flag is <strong>active</strong></h1>\n{% else %}\n    <h1>This is my base headline: Waffle Flag is <strong>inactive</strong></h1>\n{% endflag %}\n    <a href=\"{% url 'ab_test:target' %}\">Click here to see the target page</a>\n{% endblock %}\n```\n\nWhere \"`headline-flag`\" is the name of the flag you defined in the admin page.\n\n### Performance Tracking\n\nThe bandits will automatically select a winning option when the given criteria are met. When setting up a bandit, you can select the `SIGNIFICANCE LEVEL`(default is 0.05) and the `MIN VIEWS` (default is 100). \n\nAfter the `MIN VIEWS` threshold is reached, the model will perform a two-sided t-test to determine if there's significant difference in the two options (i.e. p-value < `SIGNIFICANCE LEVEL`). If this criteria is met, the bandit will then default to the winning option for all future visits to avoid potential conversion losses from testing.\n\nAs a user, you can also view the conversion rate and the upper and lower bounds of the confidence intervals at any time within the admin page.\n\n![A view of the bandit stats](docs/images/bandit-stats.png)\n",
    "bugtrack_url": null,
    "license": "Apache 2.0",
    "summary": "A package enabling multi-armed bandits for site optimization and Django.",
    "version": "0.1.6",
    "project_urls": {
        "Homepage": "https://github.com/hubbs5/django-bandits"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bfabd03ce4fd70a5fd7cb3776045f3ed062cd9d290337de6a21511ea5cf6d9d2",
                "md5": "a5c0d0885d38fb0bbfe5962194130a08",
                "sha256": "6e7e797a1598eb3f587c9e0b97375c9fb44d706d930c375c2d52abccd899c674"
            },
            "downloads": -1,
            "filename": "django_bandits-0.1.6-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a5c0d0885d38fb0bbfe5962194130a08",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<3.13",
            "size": 17879,
            "upload_time": "2023-09-01T21:04:58",
            "upload_time_iso_8601": "2023-09-01T21:04:58.540032Z",
            "url": "https://files.pythonhosted.org/packages/bf/ab/d03ce4fd70a5fd7cb3776045f3ed062cd9d290337de6a21511ea5cf6d9d2/django_bandits-0.1.6-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f9bd75a8c6708851c202a069051221d5cde2f8a9fd02423515e8963e9a02107b",
                "md5": "901fec8831373470a9bd032047aa9b9f",
                "sha256": "d2b11b8accfc4f6a63e69d6aa83798268e29329b748e4ee4157dad8bf41fd562"
            },
            "downloads": -1,
            "filename": "django_bandits-0.1.6.tar.gz",
            "has_sig": false,
            "md5_digest": "901fec8831373470a9bd032047aa9b9f",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<3.13",
            "size": 16892,
            "upload_time": "2023-09-01T21:04:59",
            "upload_time_iso_8601": "2023-09-01T21:04:59.677808Z",
            "url": "https://files.pythonhosted.org/packages/f9/bd/75a8c6708851c202a069051221d5cde2f8a9fd02423515e8963e9a02107b/django_bandits-0.1.6.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-09-01 21:04:59",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "hubbs5",
    "github_project": "django-bandits",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "django-bandits"
}
        
Elapsed time: 0.73585s