mirror of
				https://github.com/django/django.git
				synced 2025-11-03 21:25:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			289 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			289 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
===============
 | 
						||
Error reporting
 | 
						||
===============
 | 
						||
 | 
						||
When you're running a public site you should always turn off the
 | 
						||
:setting:`DEBUG` setting. That will make your server run much faster, and will
 | 
						||
also prevent malicious users from seeing details of your application that can be
 | 
						||
revealed by the error pages.
 | 
						||
 | 
						||
However, running with :setting:`DEBUG` set to ``False`` means you'll never see
 | 
						||
errors generated by your site -- everyone will just see your public error pages.
 | 
						||
You need to keep track of errors that occur in deployed sites, so Django can be
 | 
						||
configured to create reports with details about those errors.
 | 
						||
 | 
						||
Email reports
 | 
						||
=============
 | 
						||
 | 
						||
Server errors
 | 
						||
-------------
 | 
						||
 | 
						||
When :setting:`DEBUG` is ``False``, Django will email the users listed in the
 | 
						||
:setting:`ADMINS` setting whenever your code raises an unhandled exception and
 | 
						||
results in an internal server error (HTTP status code 500). This gives the
 | 
						||
administrators immediate notification of any errors. The :setting:`ADMINS` will
 | 
						||
get a description of the error, a complete Python traceback, and details about
 | 
						||
the HTTP request that caused the error.
 | 
						||
 | 
						||
.. note::
 | 
						||
 | 
						||
   In order to send email, Django requires a few settings telling it
 | 
						||
   how to connect to your mail server. At the very least, you'll need
 | 
						||
   to specify :setting:`EMAIL_HOST` and possibly
 | 
						||
   :setting:`EMAIL_HOST_USER` and :setting:`EMAIL_HOST_PASSWORD`,
 | 
						||
   though other settings may be also required depending on your mail
 | 
						||
   server's configuration. Consult :doc:`the Django settings
 | 
						||
   documentation </ref/settings>` for a full list of email-related
 | 
						||
   settings.
 | 
						||
 | 
						||
By default, Django will send email from root@localhost. However, some mail
 | 
						||
providers reject all email from this address. To use a different sender
 | 
						||
address, modify the :setting:`SERVER_EMAIL` setting.
 | 
						||
 | 
						||
To activate this behavior, put the email addresses of the recipients in the
 | 
						||
:setting:`ADMINS` setting.
 | 
						||
 | 
						||
.. seealso::
 | 
						||
 | 
						||
    Server error emails are sent using the logging framework, so you can
 | 
						||
    customize this behavior by :doc:`customizing your logging configuration
 | 
						||
    </topics/logging>`.
 | 
						||
 | 
						||
404 errors
 | 
						||
----------
 | 
						||
 | 
						||
Django can also be configured to email errors about broken links (404 "page
 | 
						||
not found" errors). Django sends emails about 404 errors when:
 | 
						||
 | 
						||
* :setting:`DEBUG` is ``False``;
 | 
						||
 | 
						||
* Your :setting:`MIDDLEWARE` setting includes
 | 
						||
  :class:`django.middleware.common.BrokenLinkEmailsMiddleware`.
 | 
						||
 | 
						||
If those conditions are met, Django will email the users listed in the
 | 
						||
:setting:`MANAGERS` setting whenever your code raises a 404 and the request has
 | 
						||
a referer. It doesn't bother to email for 404s that don't have a referer --
 | 
						||
those are usually just people typing in broken URLs or broken Web bots. It also
 | 
						||
ignores 404s when the referer is equal to the requested URL, since this
 | 
						||
behavior is from broken Web bots too.
 | 
						||
 | 
						||
.. note::
 | 
						||
 | 
						||
    :class:`~django.middleware.common.BrokenLinkEmailsMiddleware` must appear
 | 
						||
    before other middleware that intercepts 404 errors, such as
 | 
						||
    :class:`~django.middleware.locale.LocaleMiddleware` or
 | 
						||
    :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware`.
 | 
						||
    Put it towards the top of your :setting:`MIDDLEWARE` setting.
 | 
						||
 | 
						||
You can tell Django to stop reporting particular 404s by tweaking the
 | 
						||
:setting:`IGNORABLE_404_URLS` setting. It should be a list of compiled
 | 
						||
regular expression objects. For example::
 | 
						||
 | 
						||
    import re
 | 
						||
    IGNORABLE_404_URLS = [
 | 
						||
        re.compile(r'\.(php|cgi)$'),
 | 
						||
        re.compile(r'^/phpmyadmin/'),
 | 
						||
    ]
 | 
						||
 | 
						||
In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not* be
 | 
						||
reported. Neither will any URL starting with ``/phpmyadmin/``.
 | 
						||
 | 
						||
The following example shows how to exclude some conventional URLs that browsers and
 | 
						||
crawlers often request::
 | 
						||
 | 
						||
    import re
 | 
						||
    IGNORABLE_404_URLS = [
 | 
						||
        re.compile(r'^/apple-touch-icon.*\.png$'),
 | 
						||
        re.compile(r'^/favicon\.ico$'),
 | 
						||
        re.compile(r'^/robots\.txt$'),
 | 
						||
    ]
 | 
						||
 | 
						||
(Note that these are regular expressions, so we put a backslash in front of
 | 
						||
periods to escape them.)
 | 
						||
 | 
						||
If you'd like to customize the behavior of
 | 
						||
:class:`django.middleware.common.BrokenLinkEmailsMiddleware` further (for
 | 
						||
example to ignore requests coming from web crawlers), you should subclass it
 | 
						||
and override its methods.
 | 
						||
 | 
						||
.. seealso::
 | 
						||
 | 
						||
    404 errors are logged using the logging framework. By default, these log
 | 
						||
    records are ignored, but you can use them for error reporting by writing a
 | 
						||
    handler and :doc:`configuring logging </topics/logging>` appropriately.
 | 
						||
 | 
						||
.. _filtering-error-reports:
 | 
						||
 | 
						||
Filtering error reports
 | 
						||
=======================
 | 
						||
 | 
						||
.. warning::
 | 
						||
 | 
						||
    Filtering sensitive data is a hard problem, and it's nearly impossible to
 | 
						||
    guarantee that sensitive won't leak into an error report. Therefore, error
 | 
						||
    reports should only be available to trusted team members and you should
 | 
						||
    avoid transmitting error reports unencrypted over the Internet (such as
 | 
						||
    through email).
 | 
						||
 | 
						||
Filtering sensitive information
 | 
						||
-------------------------------
 | 
						||
 | 
						||
.. currentmodule:: django.views.decorators.debug
 | 
						||
 | 
						||
Error reports are really helpful for debugging errors, so it is generally
 | 
						||
useful to record as much relevant information about those errors as possible.
 | 
						||
For example, by default Django records the `full traceback`_ for the
 | 
						||
exception raised, each `traceback frame`_’s local variables, and the
 | 
						||
:class:`~django.http.HttpRequest`’s :ref:`attributes<httprequest-attributes>`.
 | 
						||
 | 
						||
However, sometimes certain types of information may be too sensitive and thus
 | 
						||
may not be appropriate to be kept track of, for example a user's password or
 | 
						||
credit card number. So in addition to filtering out settings that appear to be
 | 
						||
sensitive as described in the :setting:`DEBUG` documentation, Django offers a
 | 
						||
set of function decorators to help you control which information should be
 | 
						||
filtered out of error reports in a production environment (that is, where
 | 
						||
:setting:`DEBUG` is set to ``False``): :func:`sensitive_variables` and
 | 
						||
:func:`sensitive_post_parameters`.
 | 
						||
 | 
						||
.. _`full traceback`: https://en.wikipedia.org/wiki/Stack_trace
 | 
						||
.. _`traceback frame`: https://en.wikipedia.org/wiki/Stack_frame
 | 
						||
 | 
						||
.. function:: sensitive_variables(*variables)
 | 
						||
 | 
						||
    If a function (either a view or any regular callback) in your code uses
 | 
						||
    local variables susceptible to contain sensitive information, you may
 | 
						||
    prevent the values of those variables from being included in error reports
 | 
						||
    using the ``sensitive_variables`` decorator::
 | 
						||
 | 
						||
        from django.views.decorators.debug import sensitive_variables
 | 
						||
 | 
						||
        @sensitive_variables('user', 'pw', 'cc')
 | 
						||
        def process_info(user):
 | 
						||
            pw = user.pass_word
 | 
						||
            cc = user.credit_card_number
 | 
						||
            name = user.name
 | 
						||
            ...
 | 
						||
 | 
						||
    In the above example, the values for the ``user``, ``pw`` and ``cc``
 | 
						||
    variables will be hidden and replaced with stars (`**********`) in the
 | 
						||
    error reports, whereas the value of the ``name`` variable will be
 | 
						||
    disclosed.
 | 
						||
 | 
						||
    To systematically hide all local variables of a function from error logs,
 | 
						||
    do not provide any argument to the ``sensitive_variables`` decorator::
 | 
						||
 | 
						||
        @sensitive_variables()
 | 
						||
        def my_function():
 | 
						||
            ...
 | 
						||
 | 
						||
    .. admonition:: When using multiple decorators
 | 
						||
 | 
						||
        If the variable you want to hide is also a function argument (e.g.
 | 
						||
        '``user``’ in the following example), and if the decorated function has
 | 
						||
        multiple decorators, then make sure to place ``@sensitive_variables``
 | 
						||
        at the top of the decorator chain. This way it will also hide the
 | 
						||
        function argument as it gets passed through the other decorators::
 | 
						||
 | 
						||
            @sensitive_variables('user', 'pw', 'cc')
 | 
						||
            @some_decorator
 | 
						||
            @another_decorator
 | 
						||
            def process_info(user):
 | 
						||
                ...
 | 
						||
 | 
						||
.. function:: sensitive_post_parameters(*parameters)
 | 
						||
 | 
						||
    If one of your views receives an :class:`~django.http.HttpRequest` object
 | 
						||
    with :attr:`POST parameters<django.http.HttpRequest.POST>` susceptible to
 | 
						||
    contain sensitive information, you may prevent the values of those
 | 
						||
    parameters from being included in the error reports using the
 | 
						||
    ``sensitive_post_parameters`` decorator::
 | 
						||
 | 
						||
        from django.views.decorators.debug import sensitive_post_parameters
 | 
						||
 | 
						||
        @sensitive_post_parameters('pass_word', 'credit_card_number')
 | 
						||
        def record_user_profile(request):
 | 
						||
            UserProfile.create(
 | 
						||
                user=request.user,
 | 
						||
                password=request.POST['pass_word'],
 | 
						||
                credit_card=request.POST['credit_card_number'],
 | 
						||
                name=request.POST['name'],
 | 
						||
            )
 | 
						||
            ...
 | 
						||
 | 
						||
    In the above example, the values for the ``pass_word`` and
 | 
						||
    ``credit_card_number`` POST parameters will be hidden and replaced with
 | 
						||
    stars (`**********`) in the request's representation inside the error
 | 
						||
    reports, whereas the value of the ``name`` parameter will be disclosed.
 | 
						||
 | 
						||
    To systematically hide all POST parameters of a request in error reports,
 | 
						||
    do not provide any argument to the ``sensitive_post_parameters`` decorator::
 | 
						||
 | 
						||
        @sensitive_post_parameters()
 | 
						||
        def my_view(request):
 | 
						||
            ...
 | 
						||
 | 
						||
    All POST parameters are systematically filtered out of error reports for
 | 
						||
    certain :mod:`django.contrib.auth.views` views (``login``,
 | 
						||
    ``password_reset_confirm``, ``password_change``, and ``add_view`` and
 | 
						||
    ``user_change_password`` in the ``auth`` admin) to prevent the leaking of
 | 
						||
    sensitive information such as user passwords.
 | 
						||
 | 
						||
.. _custom-error-reports:
 | 
						||
 | 
						||
Custom error reports
 | 
						||
--------------------
 | 
						||
 | 
						||
All :func:`sensitive_variables` and :func:`sensitive_post_parameters` do is,
 | 
						||
respectively, annotate the decorated function with the names of sensitive
 | 
						||
variables and annotate the ``HttpRequest`` object with the names of sensitive
 | 
						||
POST parameters, so that this sensitive information can later be filtered out
 | 
						||
of reports when an error occurs. The actual filtering is done by Django's
 | 
						||
default error reporter filter:
 | 
						||
:class:`django.views.debug.SafeExceptionReporterFilter`. This filter uses the
 | 
						||
decorators' annotations to replace the corresponding values with stars
 | 
						||
(`**********`) when the error reports are produced. If you wish to override or
 | 
						||
customize this default behavior for your entire site, you need to define your
 | 
						||
own filter class and tell Django to use it via the
 | 
						||
:setting:`DEFAULT_EXCEPTION_REPORTER_FILTER` setting::
 | 
						||
 | 
						||
    DEFAULT_EXCEPTION_REPORTER_FILTER = 'path.to.your.CustomExceptionReporterFilter'
 | 
						||
 | 
						||
You may also control in a more granular way which filter to use within any
 | 
						||
given view by setting the ``HttpRequest``’s ``exception_reporter_filter``
 | 
						||
attribute::
 | 
						||
 | 
						||
    def my_view(request):
 | 
						||
        if request.user.is_authenticated:
 | 
						||
            request.exception_reporter_filter = CustomExceptionReporterFilter()
 | 
						||
        ...
 | 
						||
 | 
						||
.. currentmodule:: django.views.debug
 | 
						||
 | 
						||
Your custom filter class needs to inherit from
 | 
						||
:class:`django.views.debug.SafeExceptionReporterFilter` and may override the
 | 
						||
following methods:
 | 
						||
 | 
						||
.. class:: SafeExceptionReporterFilter
 | 
						||
 | 
						||
.. method:: SafeExceptionReporterFilter.is_active(request)
 | 
						||
 | 
						||
    Returns ``True`` to activate the filtering operated in the other methods.
 | 
						||
    By default the filter is active if :setting:`DEBUG` is ``False``.
 | 
						||
 | 
						||
.. method:: SafeExceptionReporterFilter.get_post_parameters(request)
 | 
						||
 | 
						||
    Returns the filtered dictionary of POST parameters. By default it replaces
 | 
						||
    the values of sensitive parameters with stars (`**********`).
 | 
						||
 | 
						||
.. method:: SafeExceptionReporterFilter.get_traceback_frame_variables(request, tb_frame)
 | 
						||
 | 
						||
    Returns the filtered dictionary of local variables for the given traceback
 | 
						||
    frame. By default it replaces the values of sensitive variables with stars
 | 
						||
    (`**********`).
 | 
						||
 | 
						||
.. seealso::
 | 
						||
 | 
						||
    You can also set up custom error reporting by writing a custom piece of
 | 
						||
    :ref:`exception middleware <exception-middleware>`. If you do write custom
 | 
						||
    error handling, it's a good idea to emulate Django's built-in error handling
 | 
						||
    and only report/log errors if :setting:`DEBUG` is ``False``.
 |