Created
September 27, 2021 10:27
-
-
Save davidhalter/89f5c5a247bcb508bf2231d32b37d14b to your computer and use it in GitHub Desktop.
curl.py - A way to debug Django Requests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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