Package: django-sql-tagger
django-sql-taggerAdds a comment to SQL queries pointing to their place of originUsageInstall:pip install django-sql-taggerConfigure and add toINSTALLED_APPSin yoursettings.pyfile:INSTALLED_APPS=[...'django_sql_tagger',...]SQL_TAGGER_CODE_ROOT=BASE_DIRSQL_TAGGER_PATH_REPLACEMENTS=[(r'^myapp/','a/'),]SettingsSQL_TAGGER_CODE_ROOT- The root of your codebase. This is used to find out which stack frames belong to your
application code.SQL_TAGGER_PATH_REPLACEMENTS- A list of tuples of regular expressions and replacements. This is used to shorten
paths in the comments. For example, if you have a file at/myapp/views.pyand you want to replace/myapp/witha/, you would add(r'^myapp/', 'a/')to the list.Tagging precisionThe tagger automatically adds comments to SQL queries, pointing to the place in the code where the query was executed.
It tries to be clever in finding the right stack frame. Therefore it ignores all stack frames that don't belong
toSQL_TAGGER_CODE_ROOTand anything that subclassesModelorQuerySet.If you have a utility method that you call from multiple places, you may want to ignore it by adding@django_sql_tagger.ignore_belowto the method. This annotation makes django-sql-tagger look only at the stack frames
that were created before the annotated method was called.Tagging transactionsThis app monkey-patchestransaction.atomic, so no changes to your code are necessary.transaction.atomicnow accepts atagargument, which will be recorded in the comments of the SQL queries. Without atag, only
the filename and line number of thetransaction.atomic()call will be recorded.ExampleSee thetestsite/directory for an example project using this package.fromdjango.core.managementimportBaseCommandfromdjango.dbimportconnection,transactionfromtestapp.modelsimportWebsiteclassCommand(BaseCommand):defhandle(self,*args,**options):Website.objects.first()withtransaction.atomic():Website.objects.first()withtransaction.atomic():withtransaction.atomic():Website.objects.first()withtransaction.atomic(tag='xxx'):Website.objects.first()The above command executes the following SQL queries:/* ta/m/c/example.py:10 */SELECT"testapp_website"."id","testapp_website"."name","testapp_website"."url"FROM"testapp_website";args=();alias=defaultBEGIN;/* ta/m/c/example.py:12 |> ta/m/c/example.py:13 */SELECT"testapp_website"."id","testapp_website"."name","testapp_website"."url"FROM"testapp_website";COMMIT;BEGIN;SAVEPOINT"s140328319196032_x1";/* ta/m/c/example.py:15 |> ta/m/c/example.py:16 |> ta/m/c/example.py:17 */SELECT"testapp_website"."id","testapp_website"."name","testapp_website"."url"FROM"testapp_website";RELEASESAVEPOINT"s140328319196032_x1";COMMIT;BEGIN;/* T=xxx ta/m/c/example.py:19 |> ta/m/c/example.py:20 */SELECT"testapp_website"."id","testapp_website"."name","testapp_website"."url"FROM"testapp_website";COMMIT;The comments make it easier to identify where the SQL queries are coming from, for example when you see the query
in the database log or a database monitoring tool.LicenseGPLv3 (seeLICENSEfile)Changelog0.3.1IncludeManagerin the list of framework classes0.3.0Better precision for tagsIgnore subclasses of Model and QuerySetAdd annotation so the user can ignore utility functions0.2.1Fix AttributeError: type object 'Command' has no attribute 'code'0.2.0Monkey-patchtransaction.atomicso all transactions are tagged by default0.1.0Initial releaseDevelopmentInstall dependenciespip install -e '.[dev]'Run testscd testsite/
pytestReleaseUpdate changelog in this file.Wait for tests to pass.Create a new release on GitHub. This will trigger a new job that will publish the package to PyPI.