{"action":"created","comment":{"url":"https://api.github.com/repos/django/django/pulls/comments/29669919","id":29669919,"diff_hunk":"@@ -510,6 +530,116 @@ fictional ``foobar`` template library::\n \n See `DEP 182`_ for more information.\n \n+Debug integration for custom engines\n+------------------------------------\n+\n+.. versionadded:: 1.9\n+\n+    Debug page integration for non-Django template engines was added in Django\n+    1.9.\n+\n+The Django debug page has hooks to provide detailed information when a template\n+error arises. Custom template engines can use these hooks to enhance the\n+traceback information that appears to users. The following hooks are available:\n+\n+.. _template-postmortem:\n+\n+Template postmortem\n+~~~~~~~~~~~~~~~~~~~\n+\n+The postmortem appears when :exc:`~django.template.TemplateDoesNotExist` is\n+raised. It lists the template engines and loaders that were used when trying\n+to find a given template. For example, if two Django engines are configured,\n+the postmortem will appear like:\n+\n+.. image:: _images/postmortem.png\n+\n+Custom engines can populate the postmortem by passing the ``backend`` and\n+``tried`` arguments when raising :exc:`~django.template.TemplateDoesNotExist`.\n+Backends that use the postmortem :ref:`should specify an origin\n+<template-origin-api>` on the template object.\n+\n+Contextual line information\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+If an error happens during template parsing or rendering, Django can display\n+the line the error happened on. For example:\n+\n+.. image:: _images/template-lines.png\n+\n+Custom engines can populate this information by setting a ``template_debug``\n+attribute on exceptions raised during parsing and rendering. This attribute\n+is a :class:`dict` with the following values:\n+\n+* ``'name'``: The name of the template in which the exception occurred.\n+\n+* ``'message'``: The exception message.\n+\n+* ``'source_lines'``: The lines before, after, and including the line the\n+  exception occurred on. This is for context, so it shouldn't contain more than\n+  20 lines or so.\n+\n+* ``'line'``: The line number on which the exception occurred.\n+\n+* ``'before'``: The content on the error line before the token that raised the\n+  error.\n+\n+* ``'during'``: The token that raised the error.\n+\n+* ``'after'``: The content on the error line after the token that raised the\n+  error.\n+\n+* ``'total'``: The number of lines in ``source_lines``.\n+\n+* ``'top'``: The line number where ``source_lines`` starts.\n+\n+* ``'bottom'``: The line number where ``source_lines`` ends.\n+\n+Given the above template error, ``template_debug`` would look like::\n+\n+    {\n+        'name': '/path/to/template.html',\n+        'message': \"Invalid block tag: 'syntax'\",\n+        'source_lines': [\n+            (1, 'some\\n'),\n+            (2, 'lines\\n'),\n+            (3, 'before\\n'),\n+            (4, 'Hello {% syntax error %} {{ world }}\\n'),\n+            (5, 'some\\n'),\n+            (6, 'lines\\n'),\n+            (7, 'after\\n'),\n+            (8, ''),\n+        ],\n+        'line': 4,\n+        'before': 'Hello ',\n+        'during': '{% syntax error %}',\n+        'after': ' {{ world }}\\n',\n+        'total': 9,\n+        'bottom': 9,\n+        'top': 1,\n+    }\n+\n+.. _template-origin-api:\n+\n+Origin API and 3rd-party integration\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Django templates have an :class:`~django.template.base.Origin` object available\n+through the ``template.origin`` attribute. This enables debug information to be\n+displayed in the :ref:`template postmortem <template-postmortem>`, as well as","path":"docs/topics/templates.txt","position":153,"original_position":153,"commit_id":"4b59704f5bd3d610f487de039040b4eb12ce590e","original_commit_id":"4b59704f5bd3d610f487de039040b4eb12ce590e","user":{"login":"timgraham","id":411869,"avatar_url":"https://avatars.githubusercontent.com/u/411869?v=3","gravatar_id":"","url":"https://api.github.com/users/timgraham","html_url":"https://github.com/timgraham","followers_url":"https://api.github.com/users/timgraham/followers","following_url":"https://api.github.com/users/timgraham/following{/other_user}","gists_url":"https://api.github.com/users/timgraham/gists{/gist_id}","starred_url":"https://api.github.com/users/timgraham/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/timgraham/subscriptions","organizations_url":"https://api.github.com/users/timgraham/orgs","repos_url":"https://api.github.com/users/timgraham/repos","events_url":"https://api.github.com/users/timgraham/events{/privacy}","received_events_url":"https://api.github.com/users/timgraham/received_events","type":"User","site_admin":false},"body":"as well as in","created_at":"2015-05-05T13:57:10Z","updated_at":"2015-05-05T13:57:10Z","html_url":"https://github.com/django/django/pull/4556#discussion_r29669919","pull_request_url":"https://api.github.com/repos/django/django/pulls/4556","_links":{"self":{"href":"https://api.github.com/repos/django/django/pulls/comments/29669919"},"html":{"href":"https://github.com/django/django/pull/4556#discussion_r29669919"},"pull_request":{"href":"https://api.github.com/repos/django/django/pulls/4556"}}},"pull_request":{"url":"https://api.github.com/repos/django/django/pulls/4556","id":34080763,"html_url":"https://github.com/django/django/pull/4556","diff_url":"https://github.com/django/django/pull/4556.diff","patch_url":"https://github.com/django/django/pull/4556.patch","issue_url":"https://api.github.com/repos/django/django/issues/4556","number":4556,"state":"open","locked":false,"title":"Fixed #24119, #24120 -- Formalized debug integration for template backends","user":{"login":"prestontimmons","id":207051,"avatar_url":"https://avatars.githubusercontent.com/u/207051?v=3","gravatar_id":"","url":"https://api.github.com/users/prestontimmons","html_url":"https://github.com/prestontimmons","followers_url":"https://api.github.com/users/prestontimmons/followers","following_url":"https://api.github.com/users/prestontimmons/following{/other_user}","gists_url":"https://api.github.com/users/prestontimmons/gists{/gist_id}","starred_url":"https://api.github.com/users/prestontimmons/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prestontimmons/subscriptions","organizations_url":"https://api.github.com/users/prestontimmons/orgs","repos_url":"https://api.github.com/users/prestontimmons/repos","events_url":"https://api.github.com/users/prestontimmons/events{/privacy}","received_events_url":"https://api.github.com/users/prestontimmons/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-04-24T19:55:44Z","updated_at":"2015-05-05T13:57:10Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6d113118e8458cd5a79b990406d2bd9dc01dd06a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/django/django/pulls/4556/commits","review_comments_url":"https://api.github.com/repos/django/django/pulls/4556/comments","review_comment_url":"https://api.github.com/repos/django/django/pulls/comments{/number}","comments_url":"https://api.github.com/repos/django/django/issues/4556/comments","statuses_url":"https://api.github.com/repos/django/django/statuses/4b59704f5bd3d610f487de039040b4eb12ce590e","head":{"label":"prestontimmons:ticket-24120","ref":"ticket-24120","sha":"4b59704f5bd3d610f487de039040b4eb12ce590e","user":{"login":"prestontimmons","id":207051,"avatar_url":"https://avatars.githubusercontent.com/u/207051?v=3","gravatar_id":"","url":"https://api.github.com/users/prestontimmons","html_url":"https://github.com/prestontimmons","followers_url":"https://api.github.com/users/prestontimmons/followers","following_url":"https://api.github.com/users/prestontimmons/following{/other_user}","gists_url":"https://api.github.com/users/prestontimmons/gists{/gist_id}","starred_url":"https://api.github.com/users/prestontimmons/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prestontimmons/subscriptions","organizations_url":"https://api.github.com/users/prestontimmons/orgs","repos_url":"https://api.github.com/users/prestontimmons/repos","events_url":"https://api.github.com/users/prestontimmons/events{/privacy}","received_events_url":"https://api.github.com/users/prestontimmons/received_events","type":"User","site_admin":false},"repo":{"id":8862914,"name":"django","full_name":"prestontimmons/django","owner":{"login":"prestontimmons","id":207051,"avatar_url":"https://avatars.githubusercontent.com/u/207051?v=3","gravatar_id":"","url":"https://api.github.com/users/prestontimmons","html_url":"https://github.com/prestontimmons","followers_url":"https://api.github.com/users/prestontimmons/followers","following_url":"https://api.github.com/users/prestontimmons/following{/other_user}","gists_url":"https://api.github.com/users/prestontimmons/gists{/gist_id}","starred_url":"https://api.github.com/users/prestontimmons/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prestontimmons/subscriptions","organizations_url":"https://api.github.com/users/prestontimmons/orgs","repos_url":"https://api.github.com/users/prestontimmons/repos","events_url":"https://api.github.com/users/prestontimmons/events{/privacy}","received_events_url":"https://api.github.com/users/prestontimmons/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/prestontimmons/django","description":"The Web framework for perfectionists with deadlines.","fork":true,"url":"https://api.github.com/repos/prestontimmons/django","forks_url":"https://api.github.com/repos/prestontimmons/django/forks","keys_url":"https://api.github.com/repos/prestontimmons/django/keys{/key_id}","collaborators_url":"https://api.github.com/repos/prestontimmons/django/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/prestontimmons/django/teams","hooks_url":"https://api.github.com/repos/prestontimmons/django/hooks","issue_events_url":"https://api.github.com/repos/prestontimmons/django/issues/events{/number}","events_url":"https://api.github.com/repos/prestontimmons/django/events","assignees_url":"https://api.github.com/repos/prestontimmons/django/assignees{/user}","branches_url":"https://api.github.com/repos/prestontimmons/django/branches{/branch}","tags_url":"https://api.github.com/repos/prestontimmons/django/tags","blobs_url":"https://api.github.com/repos/prestontimmons/django/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/prestontimmons/django/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/prestontimmons/django/git/refs{/sha}","trees_url":"https://api.github.com/repos/prestontimmons/django/git/trees{/sha}","statuses_url":"https://api.github.com/repos/prestontimmons/django/statuses/{sha}","languages_url":"https://api.github.com/repos/prestontimmons/django/languages","stargazers_url":"https://api.github.com/repos/prestontimmons/django/stargazers","contributors_url":"https://api.github.com/repos/prestontimmons/django/contributors","subscribers_url":"https://api.github.com/repos/prestontimmons/django/subscribers","subscription_url":"https://api.github.com/repos/prestontimmons/django/subscription","commits_url":"https://api.github.com/repos/prestontimmons/django/commits{/sha}","git_commits_url":"https://api.github.com/repos/prestontimmons/django/git/commits{/sha}","comments_url":"https://api.github.com/repos/prestontimmons/django/comments{/number}","issue_comment_url":"https://api.github.com/repos/prestontimmons/django/issues/comments{/number}","contents_url":"https://api.github.com/repos/prestontimmons/django/contents/{+path}","compare_url":"https://api.github.com/repos/prestontimmons/django/compare/{base}...{head}","merges_url":"https://api.github.com/repos/prestontimmons/django/merges","archive_url":"https://api.github.com/repos/prestontimmons/django/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/prestontimmons/django/downloads","issues_url":"https://api.github.com/repos/prestontimmons/django/issues{/number}","pulls_url":"https://api.github.com/repos/prestontimmons/django/pulls{/number}","milestones_url":"https://api.github.com/repos/prestontimmons/django/milestones{/number}","notifications_url":"https://api.github.com/repos/prestontimmons/django/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/prestontimmons/django/labels{/name}","releases_url":"https://api.github.com/repos/prestontimmons/django/releases{/id}","created_at":"2013-03-18T20:02:22Z","updated_at":"2015-04-20T14:25:38Z","pushed_at":"2015-05-02T21:28:39Z","git_url":"git://github.com/prestontimmons/django.git","ssh_url":"git@github.com:prestontimmons/django.git","clone_url":"https://github.com/prestontimmons/django.git","svn_url":"https://github.com/prestontimmons/django","homepage":"http://www.djangoproject.com/","size":119327,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"django:master","ref":"master","sha":"3cb386b8c2b2d7d72a3778c89d5d1f997fa0cad8","user":{"login":"django","id":27804,"avatar_url":"https://avatars.githubusercontent.com/u/27804?v=3","gravatar_id":"","url":"https://api.github.com/users/django","html_url":"https://github.com/django","followers_url":"https://api.github.com/users/django/followers","following_url":"https://api.github.com/users/django/following{/other_user}","gists_url":"https://api.github.com/users/django/gists{/gist_id}","starred_url":"https://api.github.com/users/django/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/django/subscriptions","organizations_url":"https://api.github.com/users/django/orgs","repos_url":"https://api.github.com/users/django/repos","events_url":"https://api.github.com/users/django/events{/privacy}","received_events_url":"https://api.github.com/users/django/received_events","type":"Organization","site_admin":false},"repo":{"id":4164482,"name":"django","full_name":"django/django","owner":{"login":"django","id":27804,"avatar_url":"https://avatars.githubusercontent.com/u/27804?v=3","gravatar_id":"","url":"https://api.github.com/users/django","html_url":"https://github.com/django","followers_url":"https://api.github.com/users/django/followers","following_url":"https://api.github.com/users/django/following{/other_user}","gists_url":"https://api.github.com/users/django/gists{/gist_id}","starred_url":"https://api.github.com/users/django/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/django/subscriptions","organizations_url":"https://api.github.com/users/django/orgs","repos_url":"https://api.github.com/users/django/repos","events_url":"https://api.github.com/users/django/events{/privacy}","received_events_url":"https://api.github.com/users/django/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/django/django","description":"The Web framework for perfectionists with deadlines.","fork":false,"url":"https://api.github.com/repos/django/django","forks_url":"https://api.github.com/repos/django/django/forks","keys_url":"https://api.github.com/repos/django/django/keys{/key_id}","collaborators_url":"https://api.github.com/repos/django/django/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/django/django/teams","hooks_url":"https://api.github.com/repos/django/django/hooks","issue_events_url":"https://api.github.com/repos/django/django/issues/events{/number}","events_url":"https://api.github.com/repos/django/django/events","assignees_url":"https://api.github.com/repos/django/django/assignees{/user}","branches_url":"https://api.github.com/repos/django/django/branches{/branch}","tags_url":"https://api.github.com/repos/django/django/tags","blobs_url":"https://api.github.com/repos/django/django/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/django/django/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/django/django/git/refs{/sha}","trees_url":"https://api.github.com/repos/django/django/git/trees{/sha}","statuses_url":"https://api.github.com/repos/django/django/statuses/{sha}","languages_url":"https://api.github.com/repos/django/django/languages","stargazers_url":"https://api.github.com/repos/django/django/stargazers","contributors_url":"https://api.github.com/repos/django/django/contributors","subscribers_url":"https://api.github.com/repos/django/django/subscribers","subscription_url":"https://api.github.com/repos/django/django/subscription","commits_url":"https://api.github.com/repos/django/django/commits{/sha}","git_commits_url":"https://api.github.com/repos/django/django/git/commits{/sha}","comments_url":"https://api.github.com/repos/django/django/comments{/number}","issue_comment_url":"https://api.github.com/repos/django/django/issues/comments{/number}","contents_url":"https://api.github.com/repos/django/django/contents/{+path}","compare_url":"https://api.github.com/repos/django/django/compare/{base}...{head}","merges_url":"https://api.github.com/repos/django/django/merges","archive_url":"https://api.github.com/repos/django/django/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/django/django/downloads","issues_url":"https://api.github.com/repos/django/django/issues{/number}","pulls_url":"https://api.github.com/repos/django/django/pulls{/number}","milestones_url":"https://api.github.com/repos/django/django/milestones{/number}","notifications_url":"https://api.github.com/repos/django/django/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/django/django/labels{/name}","releases_url":"https://api.github.com/repos/django/django/releases{/id}","created_at":"2012-04-28T02:47:18Z","updated_at":"2015-05-05T13:18:29Z","pushed_at":"2015-05-05T13:23:06Z","git_url":"git://github.com/django/django.git","ssh_url":"git@github.com:django/django.git","clone_url":"https://github.com/django/django.git","svn_url":"https://github.com/django/django","homepage":"https://www.djangoproject.com/","size":288611,"stargazers_count":14061,"watchers_count":14061,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":5582,"mirror_url":null,"open_issues_count":78,"forks":5582,"open_issues":78,"watchers":14061,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/django/django/pulls/4556"},"html":{"href":"https://github.com/django/django/pull/4556"},"issue":{"href":"https://api.github.com/repos/django/django/issues/4556"},"comments":{"href":"https://api.github.com/repos/django/django/issues/4556/comments"},"review_comments":{"href":"https://api.github.com/repos/django/django/pulls/4556/comments"},"review_comment":{"href":"https://api.github.com/repos/django/django/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/django/django/pulls/4556/commits"},"statuses":{"href":"https://api.github.com/repos/django/django/statuses/4b59704f5bd3d610f487de039040b4eb12ce590e"}}}}