{ "info": { "author": "Kelvin Chan", "author_email": "kelvinc.25@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy" ], "description": "\n![Build Status](https://travis-ci.org/RouganStriker/django-query-debug.svg?branch=master)\n[![Coverage Status](https://coveralls.io/repos/github/RouganStriker/django-query-debug/badge.svg?branch=master)](https://coveralls.io/github/RouganStriker/django-query-debug?branch=master)\n\nA Django application containing helper methods and mixins for debugging query issues.\n\n## Installation\nInstall package using `pip install django-query-debug`.\n\nTo use this package in an existing Django application, add `django_query_debug` to `INSTALLED_APPS` in your settings file. \n\nExample:\n```python\nINSTALLED_APPS = [\n 'django_query_debug',\n ...\n]\n```\n\n## Usage\n\n### PatchDjangoDescriptors\nMonkey patches the builtin Django field descriptors to log a warning message when a query call is about to be made. \nIf the logging level is set to `DEBUG`, a stack trace will be logged to help find the line that is causing the query.\n\nSample usage:\n```python\nfrom django_query_debug.patch import PatchDjangoDescriptors\n\nPatchDjangoDescriptors() \n```\n\n### FieldUsageMixin\nA model mixin that adds field usage tracking. Useful for determining which fields can be deferred during the \ninitial DB query using `.only()` or `.exclude()`. \n\nTo use, add the mixin to any model that extends from the Django `Model` class. \nIt will wrap all model fields in that class with a custom descriptor that tracks access attempts.\n\nSample usage:\n```python\nfrom django.db import models\n\nfrom django_query_debug.mixins import FieldUsageMixin\n\nclass MyModel(FieldUsageMixin, models.Model):\n name = models.CharField(max_length=255)\n related_model = models.ForeignKey(...)\n\n```\n\nCalling `display_field_usage()` on the model will log the output field usage data. \nField usage data for any related model that inherits from `FieldUsageMixin` will also be displayed. \nTo exclude data from related models, use `display_field_usage(show_related=False)`. \nTo reset field usage data, call `reset_field_usage()` on that object.\n\nNote: If a related object is referenced more than once via different fields, each occurrence will share \nthe same field usage data because the underlying object is the same.\n\nSample output:\n```bash\n2019-03-03 15:02:41,727 [INFO] Displaying field usage for `MyModel object`:\n2019-03-03 15:02:41,727 [INFO] id: 5\n2019-03-03 15:02:41,732 [INFO] name: 1\n2019-03-03 15:02:41,733 [INFO] related_model: 1\n2019-03-03 15:02:41,733 [INFO] id: 1\n2019-03-03 15:02:41,733 [INFO] name: 1\n2019-03-03 15:02:41,733 [INFO] related_model_id: 1\n```\n\nIf you are using custom metaclasses that inherit from the `ModelBase` class, you will need to \ncombine your custom metaclass with the `django_query_debug.mixins.FieldUsageTrackerMeta` metaclass, \nand then extend the `FieldUsageMixin` mixin to use the new metaclass.\n\n### analyze_queryset\nProvides a SQL explaination of a given queryset. \nIn Django 2.1+, this is a wrapper method around the `.explain()` method\nof the queryset.\n\nSample usage:\n```python\nfrom django_query_debug.utils import analyze_queryset\n\nanalyze_queryset(Model.objets.all())\n```\n\n### analyze_block\nA context manager that outputs debug information on all queries executed within that block of code. \nOutputs details such as the SQL statement, query time, number of results, \nnumber of query duplications, and the total time taken to execute the block of \ncode divided between DB queries and everything else. \nThe `DEBUG` setting must be set to True for Django to track queries.\n\nSample usage:\n```python\nfrom django_query_debug.utils import analyze_block\n\nwith analyze_block():\n list(Model.objets.all())\n```\n\nSample output:\n```bash\n2019-03-03 15:38:10,739 [INFO] ------------------------------------------------------------\n2019-03-03 15:38:10,740 [INFO] Query 0 summary\n2019-03-03 15:38:11,014 [INFO] SQL Statement:\nSELECT \"mock_models_simplerelatedmodel\".\"id\",\n \"mock_models_simplerelatedmodel\".\"name\",\n \"mock_models_simplerelatedmodel\".\"related_model_id\",\n \"mock_models_simplerelatedmodel\".\"one_to_one_model_id\"\nFROM \"mock_models_simplerelatedmodel\"\nWHERE \"mock_models_simplerelatedmodel\".\"name\" = 'Test 2'\n\n2019-03-03 15:38:11,015 [INFO] Query time: 0.0s\n2019-03-03 15:38:11,015 [INFO] Number of results: 1\n2019-03-03 15:38:11,015 [INFO] ------------------------------------------------------------\n2019-03-03 15:38:11,016 [INFO] Query 1 summary\n2019-03-03 15:38:11,021 [INFO] SQL Statement:\nSELECT \"mock_models_simplerelatedmodel\".\"id\",\n \"mock_models_simplerelatedmodel\".\"name\",\n \"mock_models_simplerelatedmodel\".\"related_model_id\",\n \"mock_models_simplerelatedmodel\".\"one_to_one_model_id\"\nFROM \"mock_models_simplerelatedmodel\"\n\n2019-03-03 15:38:11,021 [INFO] Query time: 0.0s\n2019-03-03 15:38:11,022 [INFO] Number of results: 2\n2019-03-03 15:38:11,022 [INFO] Duplicated 2 times\n2019-03-03 15:38:11,022 [INFO] ------------------------------------------------------------\n2019-03-03 15:38:11,022 [INFO] Query 2 summary\n2019-03-03 15:38:11,028 [INFO] SQL Statement:\nSELECT \"mock_models_simplemodel\".\"id\",\n \"mock_models_simplemodel\".\"name\"\nFROM \"mock_models_simplemodel\"\nWHERE \"mock_models_simplemodel\".\"id\" = 1\n\n2019-03-03 15:38:11,029 [INFO] Query time: 0.0s\n2019-03-03 15:38:11,029 [INFO] Number of results: 1\n2019-03-03 15:38:11,029 [INFO] ============================================================\n2019-03-03 15:38:11,029 [INFO] Elapsed time: 0.00437188148499s\n2019-03-03 15:38:11,029 [INFO] Time spent querying: 0.0s (0.0%)\n2019-03-03 15:38:11,030 [INFO] Time spent otherwise: 0.00437188148499s (100.0%)\n2019-03-03 15:38:11,030 [INFO] Query count: 4\n2019-03-03 15:38:11,030 [INFO] Duplicate query count: 1\n2019-03-03 15:38:11,030 [INFO] Total objects fetched: 6\n```\n\n## Logging\nAll logs are sent to the `query_debug` logger. To enable stack traces with the query warnings, set the debug level to `DEBUG`.\n\nSample Configuration:\n\n```python\nLOGGING = {\n 'handlers': {\n 'console': {\n 'level': 'DEBUG',\n 'class': 'logging.StreamHandler',\n }\n },\n 'loggers': {\n 'query_debug': {\n 'handlers': ['console'],\n 'level': 'DEBUG',\n }\n }\n}\n``` \n\n## Django Settings:\n\n| Setting | Default | Description |\n|---------|---------|-------------|\n| ENABLE_QUERY_WARNINGS | False | Enable warnings for access to unprefetched model fields. |\n\n\n## Development\nAfter checking out repository, install using `python setup.py develop`.\n\nTo run tests, use `python setup.py test`.\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/RouganStriker/django-query-debug", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "django-query-debug", "package_url": "https://pypi.org/project/django-query-debug/", "platform": "", "project_url": "https://pypi.org/project/django-query-debug/", "project_urls": { "Homepage": "https://github.com/RouganStriker/django-query-debug" }, "release_url": "https://pypi.org/project/django-query-debug/1.0.0/", "requires_dist": [ "depocs", "django (>=1.11.0)", "sqlparse", "six (==1.12.0)", "pygments ; extra == 'sql_formatting'" ], "requires_python": ">=2.7.0", "summary": "Helper methods and mixins for debugging query issues.", "version": "1.0.0" }, "last_serial": 4891960, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "9a7017d4fe3cb6c5fc1707b1249ef778", "sha256": "a80936b783aea3d0bae72054a265622fb6217b558406ec80f80978da4127d384" }, "downloads": -1, "filename": "django_query_debug-1.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "9a7017d4fe3cb6c5fc1707b1249ef778", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7.0", "size": 10800, "upload_time": "2019-03-03T21:57:29", "url": "https://files.pythonhosted.org/packages/9e/eb/b6a4acb7df1c7ed29dc72f6dd3470b85047f8d2c7157154c7402003f5b9f/django_query_debug-1.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ea1449c478897eefbce6d206a1e34db7", "sha256": "a689b697913e4a1826c910452a0ca7735dc6f765f77efef6d3f983df3e6f3496" }, "downloads": -1, "filename": "django_query_debug-1.0.0.tar.gz", "has_sig": false, "md5_digest": "ea1449c478897eefbce6d206a1e34db7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7.0", "size": 11213, "upload_time": "2019-03-03T21:57:31", "url": "https://files.pythonhosted.org/packages/64/2f/0128aecce908d7eaa9d1e260555a53211e33d44a66f76a2fbcd510368adc/django_query_debug-1.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "9a7017d4fe3cb6c5fc1707b1249ef778", "sha256": "a80936b783aea3d0bae72054a265622fb6217b558406ec80f80978da4127d384" }, "downloads": -1, "filename": "django_query_debug-1.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "9a7017d4fe3cb6c5fc1707b1249ef778", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7.0", "size": 10800, "upload_time": "2019-03-03T21:57:29", "url": "https://files.pythonhosted.org/packages/9e/eb/b6a4acb7df1c7ed29dc72f6dd3470b85047f8d2c7157154c7402003f5b9f/django_query_debug-1.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ea1449c478897eefbce6d206a1e34db7", "sha256": "a689b697913e4a1826c910452a0ca7735dc6f765f77efef6d3f983df3e6f3496" }, "downloads": -1, "filename": "django_query_debug-1.0.0.tar.gz", "has_sig": false, "md5_digest": "ea1449c478897eefbce6d206a1e34db7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7.0", "size": 11213, "upload_time": "2019-03-03T21:57:31", "url": "https://files.pythonhosted.org/packages/64/2f/0128aecce908d7eaa9d1e260555a53211e33d44a66f76a2fbcd510368adc/django_query_debug-1.0.0.tar.gz" } ] }