[Fixed]-Django – how to filter out GET static and media messages with logging?


Recent versions of Django make it really easy to override the default logging with your own LOGGING settings.

To filter out all GET requests to the /static/ directory, add the following to your settings.py:

def skip_static_requests(record):
    return not record.args[0].startswith('GET /static/')

    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        # use Django's built in CallbackFilter to point to your filter 
        'skip_static_requests': {
            '()': 'django.utils.log.CallbackFilter',
            'callback': skip_static_requests
    'formatters': {
        # django's default formatter
        'django.server': {
            '()': 'django.utils.log.ServerFormatter',
            'format': '[%(server_time)s] %(message)s',
    'handlers': {
        # django's default handler...
        'django.server': {
            'level': 'INFO',
            'filters': ['skip_static_requests'],  # <- ...with one change
            'class': 'logging.StreamHandler',
            'formatter': 'django.server',
    'loggers': {
        # django's default logger
        'django.server': {
            'handlers': ['django.server'],
            'level': 'INFO',
            'propagate': False,

Here are all of Django’s default loggers as of 1.10, which you can override in the same way:

Here are descriptions of what Django’s default built-in loggers do:

Here’s are the docs on Django’s CallbackFilter used above to hook in the custom filter:



As a workaround, you can use this snippet (from Django Snippets):

from django.conf import settings
from django.core.servers import basehttp
from django.core.management.commands.runserver import Command as BaseCommand

class QuietWSGIRequestHandler(basehttp.WSGIRequestHandler):
    def log_message(self, format, *args):
        # Don't bother logging requests for paths under MEDIA_URL.
        if self.path.startswith(settings.MEDIA_URL):
        # can't use super as base is old-style class, so call method explicitly
        return basehttp.WSGIRequestHandler.log_message(self, format, *args)

def run(addr, port, wsgi_handler):
    server_address = (addr, port)
    httpd = basehttp.WSGIServer(server_address, QuietWSGIRequestHandler)

class Command(BaseCommand):
    def handle(self, addrport='', *args, **options):
        # monkeypatch Django to use our quiet server
        basehttp.run = run
        return super(Command, self).handle(addrport, *args, **options)

You need to user this command to run the server. It basically only override the log behaviour to drop requests which begins by the MEDIA_URL setting. Put this whole file in an installed app and run it with ./manage.py runserver_quiet (if the command file is runserver_quiet.py)

You can’t play with the logging module, because the WSGIRequestHandler doesn’t use it to display these messages. It is directly written in the stderr stream.


From Django 1.10 you can configure django.server logging for “the handling of requests received by the server invoked by the runserver command”. This is a quick way to filter out the media requests and to focus on your logger info.

Add to django logging settings:

loggers: {
    'django.server': {
        'handlers': ['console'],
        'level': 'ERROR'  # or INFO if you want to see the log

Django Documentation ref: Logging: django-server



from django.core.servers.basehttp import WSGIRequestHandler

# Grab the original log_message method.
_log_message = WSGIRequestHandler.log_message

def log_message(self, *args):
    # Don't log if path starts with /static/
    if self.path.startswith("/static/"):
        return _log_message(self, *args)

# Replace log_message with our custom one.
WSGIRequestHandler.log_message = log_message

# Import the original runserver management command
from django.core.management.commands.runserver import Command

Hat tip https://code.djangoproject.com/ticket/25704


Leave a comment