Repository: loftylabs/django-developer-panel
Branch: master
Commit: 52fd2666a158
Files: 6
Total size: 10.7 KB
Directory structure:
gitextract_ugqg95fk/
├── .gitignore
├── LICENSE
├── README.md
├── djdev_panel/
│ ├── __init__.py
│ └── middleware.py
└── setup.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# IPython Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# dotenv
.env
# virtualenv
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
================================================
FILE: LICENSE
================================================
BSD 3-Clause License
Copyright (c) 2017, Lofty Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: README.md
================================================
# django-developer-panel

## Installation
Install this module with pip:
pip install django-developer-panel
Add the Developer Panel middleware to your application's `settings.py` and make sure `DEBUG` is enabled:
DEBUG = True
MIDDLEWARE = [
'djdev_panel.middleware.DebugMiddleware', # <--- this guy
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
You're ready to go. Install the [Chrome plugin](https://github.com/loftylabs/djdevpanel-devtools) and get started!
================================================
FILE: djdev_panel/__init__.py
================================================
================================================
FILE: djdev_panel/middleware.py
================================================
import json
from collections import OrderedDict
from collections import defaultdict
import django
import inspect
import re
from django.conf import settings
from django.core import serializers
from django.core.checks import run_checks
from django.utils.encoding import force_text
from django.db import connection
from django.views.debug import get_safe_settings
from django.utils.functional import Promise
from django.core.serializers.json import DjangoJSONEncoder
try:
from django.urls import resolve
except ImportError:
from django.core.urlresolvers import resolve
from django.views.generic.base import ContextMixin
_HTML_TYPES = ('text/html', 'application/xhtml+xml')
class LazyEncoder(DjangoJSONEncoder):
def default(self, obj):
if isinstance(obj, Promise):
return force_text(obj)
return super(LazyEncoder, self).default(obj)
def debug_payload(request, response, view_data):
current_session = {}
if 'django.contrib.sessions' in settings.INSTALLED_APPS:
if request.session.items():
for k,v in request.session.items():
current_session[k] = v
if request.user.is_anonymous:
user_data = "[\"Anonymous User\"]"
else:
user_data = serializers.serialize("json", [request.user])
resolved_url = resolve(request.path)
view = {
'view_name': resolved_url._func_path,
'view_args': resolved_url.args,
'view_kwargs': resolved_url.kwargs,
'view_methods': VIEW_METHOD_DATA,
'cbv': view_data.get('cbv', False),
'bases': view_data.get('bases', []),
}
checks = {}
raw_checks = run_checks(include_deployment_checks=True)
for check in raw_checks:
checks[check.id] = check.msg
json_friendly_settings = OrderedDict()
s = get_safe_settings()
for key in sorted(s.keys()):
json_friendly_settings[key] = str(s[key])
payload = {
'version': django.VERSION,
'current_user': json.loads(user_data)[0],
'db_queries': connection.queries,
'session': current_session,
'view_data': view,
'url_name': resolved_url.url_name,
'url_namespaces': resolved_url.namespaces,
'checks': checks,
'settings': json_friendly_settings
}
payload_script = "<script>var dj_chrome = {};</script>".format(json.dumps(payload,
cls=LazyEncoder))
return payload_script
VIEW_METHOD_WHITEIST = [
'get_context_data',
'get_template_names',
'get_queryset',
'get_object',
'get_form_class',
'get_form_kwargs',
'get_redirect_field_name',
'get_slug_field',
'get_context_object_name',
'get_login_url',
'http_method_not_allowed',
]
VIEW_METHOD_DATA = {}
PATCHED_METHODS = defaultdict(list)
def record_view_data(f):
def wrapper(self, *args, **kwargs):
retval = f(self, *args, **kwargs)
VIEW_METHOD_DATA[f.__name__] = {
'args': repr(args),
'kwargs': repr(kwargs),
'return': repr(retval)
}
return retval
return wrapper
def decorate_method(klass, method):
attached_method = getattr(klass, method)
patched_method = record_view_data(attached_method)
setattr(klass, method, patched_method)
return patched_method
class DebugMiddleware:
"""
Should be new-style and old-style compatible.
"""
def __init__(self, next_layer=None):
"""We allow next_layer to be None because old-style middlewares
won't accept any argument.
"""
self.get_response = next_layer
def process_view(self, request, view_func, view_args, view_kwargs):
"""
Collect data on Class-Based Views
"""
# Purge data in view method cache
# Python 3's keys() method returns an iterator, so force evaluation before iterating.
view_keys = list(VIEW_METHOD_DATA.keys())
for key in view_keys:
del VIEW_METHOD_DATA[key]
self.view_data = {}
try:
cbv = view_func.view_class
except AttributeError:
cbv = False
if cbv:
self.view_data['cbv'] = True
klass = view_func.view_class
self.view_data['bases'] = [base.__name__ for base in inspect.getmro(klass)]
# Inject with drugz
for member in inspect.getmembers(view_func.view_class):
# Check that we are interested in capturing data for this method
# and ensure that a decorated method is not decorated multiple times.
if member[0] in VIEW_METHOD_WHITEIST and member[0] not in PATCHED_METHODS[klass]:
decorate_method(klass, member[0])
PATCHED_METHODS[klass].append(member[0])
def process_template_response(self, request, response):
if response.context_data is None:
return response
view = response.context_data.get('view', None)
if ContextMixin in self.view_data.get('bases', []):
self.view_data['context'] = view.get_context_data()
return response
def process_request(self, request):
"""Let's handle old-style request processing here, as usual."""
# Do something with request
# Probably return None
# Or return an HttpResponse in some cases
def process_response(self, request, response):
"""Let's handle old-style response processing here, as usual."""
# For debug only.
if not settings.DEBUG:
return response
# Check for responses where the data can't be inserted.
content_encoding = response.get('Content-Encoding', '')
content_type = response.get('Content-Type', '').split(';')[0]
if any((getattr(response, 'streaming', False),
'gzip' in content_encoding,
content_type not in _HTML_TYPES)):
return response
content = force_text(response.content, encoding=settings.DEFAULT_CHARSET)
pattern = re.escape('</body>')
bits = re.split(pattern, content, flags=re.IGNORECASE)
if len(bits) > 1:
bits[-2] += debug_payload(request, response, self.view_data)
response.content = "</body>".join(bits)
if response.get('Content-Length', None):
response['Content-Length'] = len(response.content)
return response
def __call__(self, request):
"""Handle new-style middleware here."""
response = self.process_request(request)
if response is None:
# If process_request returned None, we must call the next middleware or
# the view. Note that here, we are sure that self.get_response is not
# None because this method is executed only in new-style middlewares.
response = self.get_response(request)
response = self.process_response(request, response)
return response
================================================
FILE: setup.py
================================================
from distutils.core import setup
setup(
name='django-developer-panel',
version='0.1.2',
description='Django bindings for the Django Developer Panel Chrome extension.',
author='Casey Kinsey / Lofty Labs',
author_email='casey@hirelofty.com',
url='https://github.com/loftylabs/django-developer-panel',
packages=['djdev_panel'],
)
gitextract_ugqg95fk/ ├── .gitignore ├── LICENSE ├── README.md ├── djdev_panel/ │ ├── __init__.py │ └── middleware.py └── setup.py
SYMBOL INDEX (12 symbols across 1 files)
FILE: djdev_panel/middleware.py
class LazyEncoder (line 30) | class LazyEncoder(DjangoJSONEncoder):
method default (line 31) | def default(self, obj):
function debug_payload (line 37) | def debug_payload(request, response, view_data):
function record_view_data (line 109) | def record_view_data(f):
function decorate_method (line 123) | def decorate_method(klass, method):
class DebugMiddleware (line 130) | class DebugMiddleware:
method __init__ (line 135) | def __init__(self, next_layer=None):
method process_view (line 141) | def process_view(self, request, view_func, view_args, view_kwargs):
method process_template_response (line 173) | def process_template_response(self, request, response):
method process_request (line 185) | def process_request(self, request):
method process_response (line 191) | def process_response(self, request, response):
method __call__ (line 219) | def __call__(self, request):
Condensed preview — 6 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (12K chars).
[
{
"path": ".gitignore",
"chars": 1045,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "LICENSE",
"chars": 1510,
"preview": "BSD 3-Clause License\n\nCopyright (c) 2017, Lofty Labs\nAll rights reserved.\n\nRedistribution and use in source and binary f"
},
{
"path": "README.md",
"chars": 1011,
"preview": "# django-developer-panel\n. The extraction includes 6 files (10.7 KB), approximately 2.5k tokens, and a symbol index with 12 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.