123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- ======================
- System check framework
- ======================
- .. versionadded:: 1.7
- .. module:: django.core.checks
- The system check framework is a set of static checks for validating Django
- projects. It detects common problems and provides hints for how to fix them.
- The framework is extensible so you can easily add your own checks.
- Checks can be triggered explicitly via the :djadmin:`check` command. Checks are
- triggered implicitly before most commands, including :djadmin:`runserver` and
- :djadmin:`migrate`. For performance reasons, the checks are not performed if
- :setting:`DEBUG` is set to ``False``.
- Serious errors will prevent Django commands (such as :djadmin:`runserver`) from
- running at all. Minor problems are reported to the console. If you have inspected
- the cause of a warning and are happy to ignore it, you can hide specific warnings
- using the :setting:`SILENCED_SYSTEM_CHECKS` setting in your project settings file.
- Writing your own checks
- =======================
- The framework is flexible and allows you to write functions that perform
- any other kind of check you may require. The following is an example stub
- check function::
- from django.core.checks import register
- @register()
- def example_check(app_configs, **kwargs):
- errors = []
- # ... your check logic here
- return errors
- The check function *must* accept an ``app_configs`` argument; this argument is
- the list of applications that should be inspected. If None, the check must be
- run on *all* installed apps in the project. The ``**kwargs`` argument is required
- for future expansion.
- Messages
- --------
- The function must return a list of messages. If no problems are found as a result
- of the check, the check function must return an empty list.
- .. class:: CheckMessage(level, msg, hint, obj=None, id=None)
- The warnings and errors raised by the check method must be instances of
- :class:`~django.core.checks.CheckMessage`. An instance of
- :class:`~django.core.checks.CheckMessage` encapsulates a single reportable
- error or warning. It also provides context and hints applicable to the
- message, and a unique identifier that is used for filtering purposes.
- The concept is very similar to messages from the :doc:`message
- framework </ref/contrib/messages>` or the :doc:`logging framework
- </topics/logging>`. Messages are tagged with a ``level`` indicating the
- severity of the message.
- Constructor arguments are:
- ``level``
- The severity of the message. Use one of the
- predefined values: ``DEBUG``, ``INFO``, ``WARNING``, ``ERROR``,
- ``CRITICAL``. If the level is greater or equal to ``ERROR``, then Django
- will prevent management commands from executing. Messages with
- level lower than ``ERROR`` (i.e. warnings) are reported to the console,
- but can be silenced.
- ``msg``
- A short (less than 80 characters) string describing the problem. The string
- should *not* contain newlines.
- ``hint``
- A single-line string providing a hint for fixing the problem. If no hint
- can be provided, or the hint is self-evident from the error message, a
- value of ``None`` can be used::
- Error('error message') # Will not work.
- Error('error message', None) # Good
- Error('error message', hint=None) # Better
- ``obj``
- Optional. An object providing context for the message (for example, the
- model where the problem was discovered). The object should be a model, field,
- or manager or any other object that defines ``__str__`` method (on
- Python 2 you need to define ``__unicode__`` method). The method is used while
- reporting all messages and its result precedes the message.
- ``id``
- Optional string. A unique identifier for the issue. Identifiers should
- follow the pattern ``applabel.X001``, where ``X`` is one of the letters
- ``CEWID``, indicating the message severity (``C`` for criticals,
- ``E`` for errors and so). The number can be allocated by the application,
- but should be unique within that application.
- There are also shortcuts to make creating messages with common levels easier.
- When using these methods you can omit the ``level`` argument because it is
- implied by the class name.
- .. class:: Debug(msg, hint, obj=None, id=None)
- .. class:: Info(msg, hint, obj=None, id=None)
- .. class:: Warning(msg, hint, obj=None, id=None)
- .. class:: Error(msg, hint, obj=None, id=None)
- .. class:: Critical(msg, hint, obj=None, id=None)
- Messages are comparable. That allows you to easily write tests::
- from django.core.checks import Error
- errors = checked_object.check()
- expected_errors = [
- Error(
- 'an error',
- hint=None,
- obj=checked_object,
- id='myapp.E001',
- )
- ]
- self.assertEqual(errors, expected_errors)
- Registering and labeling checks
- -------------------------------
- Lastly, your check function must be registered explicitly with system check
- registry.
- .. function:: register(*tags)(function)
- You can pass as many tags to ``register`` as you want in order to label your
- check. Tagging checks is useful since it allows you to run only a certain
- group of checks. For example, to register a compatibility check, you would
- make the following call::
- from django.core.checks import register
- @register('compatibility')
- def my_check(app_configs, **kwargs):
- # ... perform compatibility checks and collect errors
- return errors
- .. _field-checking:
- Field, Model, and Manager checks
- --------------------------------
- In some cases, you won't need to register your check function -- you can
- piggyback on an existing registration.
- Fields, models, and model managers all implement a ``check()`` method that is
- already registered with the check framework. If you want to add extra checks,
- you can extend the implementation on the base class, perform any extra
- checks you need, and append any messages to those generated by the base class.
- It's recommended the you delegate each check to a separate methods.
- Consider an example where you are implementing a custom field named
- ``RangedIntegerField``. This field adds ``min`` and ``max`` arguments to the
- constructor of ``IntegerField``. You may want to add a check to ensure that users
- provide a min value that is less than or equal to the max value. The following
- code snippet shows how you can implement this check::
- from django.core import checks
- from django.db import models
- class RangedIntegerField(models.IntegerField):
- def __init__(self, min=None, max=None, **kwargs):
- super(RangedIntegerField, self).__init__(**kwargs)
- self.min = min
- self.max = max
- def check(self, **kwargs):
- # Call the superclass
- errors = super(RangedIntegerField, self).check(**kwargs)
- # Do some custom checks and add messages to `errors`:
- errors.extend(self._check_min_max_values(**kwargs))
- # Return all errors and warnings
- return errors
- def _check_min_max_values(self, **kwargs):
- if (self.min is not None and
- self.max is not None and
- self.min > self.max):
- return [
- checks.Error(
- 'min greated than max.',
- hint='Decrease min or increase max.',
- obj=self,
- id='myapp.E001',
- )
- ]
- # When no error, return an empty list
- return []
- If you wanted to add checks to a model manager, you would take the same
- approach on your subclass of :class:`~django.db.models.Manager`.
- If you want to add a check to a model class, the approach is *almost* the same:
- the only difference is that the check is a classmethod, not an instance method::
- class MyModel(models.Model):
- @classmethod
- def check(cls, **kwargs):
- errors = super(MyModel, cls).check(**kwargs)
- # ... your own checks ...
- return errors
|