Skip to content

Instantly share code, notes, and snippets.

@davidhalter
Created September 27, 2021 10:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidhalter/89f5c5a247bcb508bf2231d32b37d14b to your computer and use it in GitHub Desktop.
Save davidhalter/89f5c5a247bcb508bf2231d32b37d14b to your computer and use it in GitHub Desktop.
curl.py - A way to debug Django Requests
import logging
import pdb
import time
from contextlib import contextmanager
from django.core.management.base import BaseCommand
from django.test import Client
from django.conf import settings
from django.db import connection
from <your-app>.models import User
logger = logging.getLogger(__name__)
@contextmanager
def log_time_used(logger, name):
start = time.time()
yield
used = time.time() - start
logger.debug('Used time for {}: {:.2f} ms'.format(name, used * 1000))
class Command(BaseCommand):
def handle(self, *, use_pdb, **kwargs):
"""
Create requests against Django, works a bit like curl.
"""
settings.DEBUG = False
try:
self._handle(**kwargs)
except Exception:
if use_pdb:
pdb.post_mortem()
raise
def _handle(self, *, url, request, as_user, use_profiler, profile_sort,
no_content_output, queries, **kwargs):
@log_time_used(logger, 'request took')
def do_request():
c = Client()
if as_user is not None:
user = User.get_by_email(as_user)
c.force_login(user)
try:
response = getattr(c, request.lower())(url, HTTP_HOST=host)
except Exception:
pdb.pm()
raise
print(response)
return response
if queries:
connection.force_debug_cursor = True
log = logging.getLogger('django.db.backends')
log.setLevel(logging.DEBUG)
log.addHandler(logging.StreamHandler())
host = settings.ALLOWED_HOSTS[0]
if use_profiler:
# TODO Python 3.8+, use a context manager.
pr = cProfile.Profile()
pr.enable()
response = do_request()
pr.disable()
pr.print_stats(sort=profile_sort)
else:
response = do_request()
if not no_content_output:
print(response.content.decode('utf-8'))
def add_arguments(self, parser):
parser.add_argument(
'url',
help='URL to do make a request')
parser.add_argument(
'-X',
'--request',
type=str,
default='get',
help='Request type, e.g. GET or POST')
parser.add_argument(
'-u',
'--as-user',
type=str,
help='Provide an email to log in as a specific user.')
parser.add_argument(
'--profile',
action='store_true',
dest='use_profiler',
help='Runs the Python profiler over a request.')
parser.add_argument(
'--profile-sort',
type=str,
default='tottime',
help='Useful for sorting profile output differently, useful is e.g. `cumtime`')
parser.add_argument(
'--queries',
action='store_true',
help='Print the queries that are used')
parser.add_argument(
'-O',
'--no-content-output',
action='store_true',
help='Does not print the reponse output for a request.')
parser.add_argument(
'--pdb',
action='store_true',
dest='use_pdb',
help='For debugging exceptions in the command.')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment