{{ proc.headertexttst.payload.1|default:\"Default description text.\" }}
\n```\n\nSee [How invalid variables are handled](https://docs.djangoproject.com/en/dev/ref/templates/api/#invalid-template-variables) in the Django template documentation for more details.\n\n### JavaScript\n\nIf you want to use Proctor test group assignments from browser-side JavaScript, you'll have to provide the values you want to use to your JavaScript through Django's templating language.\n\nA simple way to do this is to define global JavaScript variables in a script tag in your HTML template with the values your code will use:\n\n```htmldjango\n\n```\n\nFor strings, wrap the template output tag in quotes. Use the [escapejs](https://docs.djangoproject.com/en/dev/ref/templates/builtins/#escapejs) filter so that special characters like quotes and angle brackets are correctly placed into your JavaScript.\n\nSome people place script tags like this in a template block like \"js\" so that these special values appear in a consistent place alongside other script includes.\n\nYou can use these global variables in your JavaScript static files to implement your tests:\n\n```js\n$(function() {\n if (buttoncolortstgroup === \"blue\") {\n $(\".buttonone\").css(\"background\", \"#00f\");\n } else if (buttoncolortstgroup === \"green\") {\n $(\".buttonone\").css(\"background\", \"#0f0\");\n } else {\n $(\".buttonone\").css(\"background\", \"#888\");\n }\n\n if (usenewfeature) {\n $(\".buttontwo\").show();\n }\n\n $(\".buttonthree\").text(buttontext);\n});\n```\n\nThis is just one way of accessing Proctor test groups from the browser. Use whatever makes the most sense for your project.\n\nAnother way is templating your JavaScript directly by placing your code in HTML and mixing your Django template tags with JavaScript code. You could even template your .js files instead of serving them statically. However, these two alternatives can be messy and are not best practices.\n\nIf your application is complex enough, you could even consider making a Django view that returns some test groups or payloads and have your JavaScript make an AJAX request to get them.\n\n### Logging\n\nTo compare metrics between two different test groups, you can log each request's assigned test groups in addition to any metrics you want to track.\n\ndjango-proctor provides a simple comma-separated representation of all the Proctor test groups that the user is in for logging purposes:\n\n```py\nprint str(request.proc)\n# -> \"buttoncolortst1,countryalgotst0,newfeaturerollout0\"\n```\n\nThis output only includes non-negative test groups, as -1 typically means inactive groups that should not be logged.\n\nThe `proc` object also has a method to obtain the list of test groups before joining with a comma:\n\n```py\nprint request.proc.get_group_string_list()\n# -> ['buttoncolortst1', 'countryalgotst0', 'newfeaturerollout0']\n```\n\n### prforceGroups\n\nTo test the implementation of your test group behavior, privileged users can attach a `prforceGroups` query parameter to their site's URL to force themselves into certain test groups:\n\n```\nhttp://django.example.com/?prforceGroups=buttoncolortst2,countryalgotst0\n```\n\nThe format is simply the test name followed by the bucket value (not the name), with all test groups separated by commas.\n\nThe value of `prforceGroups` is set as a session cookie. Your browser will be forced into those groups until your browser is closed. You can also set an empty prforceGroups to clear the cookie:\n\n```\nhttp://django.example.com/?prforceGroups=\n```\n\nThe tests and bucket values specified in `prforceGroups` must exist in the Proctor test matrix.\n\n## Using Proctor from Other Python Frameworks\n\ndjango-proctor was designed primarily for Django as that is the framework that we (the Indeed Labs team) primarily use.\n\nHowever, these modules would be usable in other Python frameworks with some minor modifications:\n\n`api`, `cache*`, `groups`, `identify`, `lazy`\n\ncache unfortunately has some Django mixed in for some of its subclasses. It imports django.core.cache, it uses Django in subclasses, and the abstract Cacher interface takes `request` as a parameter (because `SessionCacher` needs it, but it can safely be None for all other subclasses).\n\nAlso, identify.py imports from django settings for similar reasons when looking up account details.\n\nIf this is a significant problem for you, ask us to split this into two packages: one for Python, and one for Django that has the former as a dependency. Or contribute a solution that splits the packages up.\n\nWhen implementing Proctor in other frameworks, use `middleware.py` to see how we implemented this for Django. We handle providing context variables and identifiers through subclassing. Other implementations could register functions (through decorators or otherwise) to provide these details. Also, note how the prforceGroups query parameter and cookie is handled.\n\n\n## Testing\n\nThis project uses [`tox` for executing tests](https://tox.readthedocs.io/en/latest/). To run tests\nlocally, cd into your project and run\n\n $ tox\n\nUnderneath the hood, `tox` is just running\n[`pytest` for test discovery and execution](https://docs.pytest.org/en/latest/). Test arguments can\nbe passed through into `pytest` by adding `--` after your `tox` command. For example, you can\nisolate a test file or test method using the following:\n\n $ tox -- proctor/tests/test_identify.py\n $ tox -- proctor/tests/test_identify.py::TestIdentifyGroups::test_requested_group_resolved\n\nwhere `pytest` uses a double colon as a test class/method/function separator\n\nBy default, `pytest` captures output, which prevents debugging with breakpoints. If you need to\ndebug the tests, you can run either of the following:\n\n $ tox -- --capture=no\n $ tox -- -s\n\nYou can then add a break point to a test by adding the following to your python code:\n\n```python\nimport pdb; pdb.set_trace()\n```\n\n\n## See Also\n\n* [Proctor Pipet](https://github.com/indeedeng/proctor-pipet)\n\n* [Proctor Documentation](http://indeedeng.github.io/proctor/)\n\n* [Proctor Github Repo](https://github.com/indeedeng/proctor)\n\n* [Proctor Webapp](https://github.com/indeedeng/proctor-webapp) for editing the test matrix.\n\n* [indeedeng-proctor-users](https://groups.google.com/forum/#!forum/indeedeng-proctor-users) for questions and comments.\n\n* [Proctor Blog Post](http://engineering.indeed.com/blog/2014/06/proctor-a-b-testing-framework/) on the Indeed Engineering blog.\n\n* [Proctor Tech Talk](http://engineering.indeed.com/talks/managing-experiments-behavior-dynamically-proctor/)\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/indeedeng/django-proctor", "keywords": "", "license": "Apache", "maintainer": "", "maintainer_email": "", "name": "django-proctor", "package_url": "https://pypi.org/project/django-proctor/", "platform": "", "project_url": "https://pypi.org/project/django-proctor/", "project_urls": { "Homepage": "https://github.com/indeedeng/django-proctor" }, "release_url": "https://pypi.org/project/django-proctor/1.0.4/", "requires_dist": [ "Django", "ndg-httpsclient", "pyOpenSSL", "requests" ], "requires_python": "", "summary": "Django library for interacting with the Proctor A/B testing framework", "version": "1.0.4" }, "last_serial": 5368494, "releases": { "0.0.8": [ { "comment_text": "", "digests": { "md5": "fc855083ce68c2b9e35fd90a530547bf", "sha256": "7908e0e7b1b80e587b90ea00a2c144bdaf8517053a32417996229d3dd962193b" }, "downloads": -1, "filename": "django_proctor-0.0.8-py2-none-any.whl", "has_sig": false, "md5_digest": "fc855083ce68c2b9e35fd90a530547bf", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 1106, "upload_time": "2018-07-26T15:33:43", "url": "https://files.pythonhosted.org/packages/ed/34/a5160122c1c35a1c73562d8beafd8611183c82e0ff26ce9b24aa8b495e0e/django_proctor-0.0.8-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d267d820e652ecb6799e96acb9551ab9", "sha256": "75d4cb0283c845a07e8cfbd633a09ce118b31e7a882312e6818ffc3bfa122052" }, "downloads": -1, "filename": "django-proctor-0.0.8.tar.gz", "has_sig": false, "md5_digest": "d267d820e652ecb6799e96acb9551ab9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 696, "upload_time": "2018-07-26T15:33:44", "url": "https://files.pythonhosted.org/packages/65/bf/8f511cc212a56150c23de3494c4686ee9e7cb42ff4e35e223c7d431229e1/django-proctor-0.0.8.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "6c0d807109392a1ddd4e846c5ffd3c61", "sha256": "281a6b1dc72e7b92ccdcb13f4d8968df26dc7af15c8db97967636498dfe65cd8" }, "downloads": -1, "filename": "django_proctor-1.0.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6c0d807109392a1ddd4e846c5ffd3c61", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 38917, "upload_time": "2019-06-06T17:00:53", "url": "https://files.pythonhosted.org/packages/55/6b/78add5f8cff114424a007fee99a3cff93fa89a49c52aed217e0ed53b2e48/django_proctor-1.0.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "83259e7dd8457d3e40589cf6c3354a8c", "sha256": "aec82871c634f7cf7785ed3158d2fbefee345d4bd436e74de69abed80b0d583b" }, "downloads": -1, "filename": "django-proctor-1.0.3.tar.gz", "has_sig": false, "md5_digest": "83259e7dd8457d3e40589cf6c3354a8c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34262, "upload_time": "2019-06-06T17:00:54", "url": "https://files.pythonhosted.org/packages/df/a3/cc96e2d544b02067b84af7645d70c391a228932ac2b09600f12a99e9043e/django-proctor-1.0.3.tar.gz" } ], "1.0.3rc1": [ { "comment_text": "", "digests": { "md5": "336d8e6c13a16e82a305db01c79aa05b", "sha256": "ff900282d561fb56cf8b90c5a73dadc9ce52831f7d0f83dc33bcdd0cb4b40fb5" }, "downloads": -1, "filename": "django_proctor-1.0.3rc1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "336d8e6c13a16e82a305db01c79aa05b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 38955, "upload_time": "2019-06-06T16:46:52", "url": "https://files.pythonhosted.org/packages/02/ae/faac7906a825fc0ea49dc3cebf427375d5957c34a807884aaa2c80ee5dec/django_proctor-1.0.3rc1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c84c56e5833722519d8884c1ea86ea88", "sha256": "a0d2e1744054e070d5775a39913b257d5c906e9a15d28d3110de12582aafa3f5" }, "downloads": -1, "filename": "django-proctor-1.0.3rc1.tar.gz", "has_sig": false, "md5_digest": "c84c56e5833722519d8884c1ea86ea88", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34264, "upload_time": "2019-06-06T16:46:54", "url": "https://files.pythonhosted.org/packages/91/7e/cb69e32e594716da607fad7ceffae812e5181d45189b6b4b84b7c852bbc5/django-proctor-1.0.3rc1.tar.gz" } ], "1.0.4": [ { "comment_text": "", "digests": { "md5": "91c11949cc464a80dc425c40582bfeb5", "sha256": "1413d313b2174ea782b62cf4a7588358c3036d487770257c97768f2649e9a2d9" }, "downloads": -1, "filename": "django_proctor-1.0.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "91c11949cc464a80dc425c40582bfeb5", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 38947, "upload_time": "2019-06-06T18:33:33", "url": "https://files.pythonhosted.org/packages/8e/d8/36cdb5b670033d854f6b898184452dc57c56bfa855e26089769fa091d85c/django_proctor-1.0.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4af56628cf0bf47266a7bffa9823b1c7", "sha256": "3e8f649acbfef6a6e46cdfeafc00aea064f21ca44978a8dc60988c6d0ab6105f" }, "downloads": -1, "filename": "django-proctor-1.0.4.tar.gz", "has_sig": false, "md5_digest": "4af56628cf0bf47266a7bffa9823b1c7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34272, "upload_time": "2019-06-06T18:33:35", "url": "https://files.pythonhosted.org/packages/1c/16/1debec3cbdda322486e1775fff9c80dbafd9dbb54c9cb16185ff590cd9b1/django-proctor-1.0.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "91c11949cc464a80dc425c40582bfeb5", "sha256": "1413d313b2174ea782b62cf4a7588358c3036d487770257c97768f2649e9a2d9" }, "downloads": -1, "filename": "django_proctor-1.0.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "91c11949cc464a80dc425c40582bfeb5", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 38947, "upload_time": "2019-06-06T18:33:33", "url": "https://files.pythonhosted.org/packages/8e/d8/36cdb5b670033d854f6b898184452dc57c56bfa855e26089769fa091d85c/django_proctor-1.0.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4af56628cf0bf47266a7bffa9823b1c7", "sha256": "3e8f649acbfef6a6e46cdfeafc00aea064f21ca44978a8dc60988c6d0ab6105f" }, "downloads": -1, "filename": "django-proctor-1.0.4.tar.gz", "has_sig": false, "md5_digest": "4af56628cf0bf47266a7bffa9823b1c7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34272, "upload_time": "2019-06-06T18:33:35", "url": "https://files.pythonhosted.org/packages/1c/16/1debec3cbdda322486e1775fff9c80dbafd9dbb54c9cb16185ff590cd9b1/django-proctor-1.0.4.tar.gz" } ] }