1. ======================
    
  2. System check framework
    
  3. ======================
    
  4. 
    
  5. .. module:: django.core.checks
    
  6. 
    
  7. The system check framework is a set of static checks for validating Django
    
  8. projects. It detects common problems and provides hints for how to fix them.
    
  9. The framework is extensible so you can easily add your own checks.
    
  10. 
    
  11. Checks can be triggered explicitly via the :djadmin:`check` command. Checks are
    
  12. triggered implicitly before most commands, including :djadmin:`runserver` and
    
  13. :djadmin:`migrate`. For performance reasons, checks are not run as part of the
    
  14. WSGI stack that is used in deployment. If you need to run system checks on your
    
  15. deployment server, trigger them explicitly using :djadmin:`check`.
    
  16. 
    
  17. Serious errors will prevent Django commands (such as :djadmin:`runserver`) from
    
  18. running at all. Minor problems are reported to the console. If you have inspected
    
  19. the cause of a warning and are happy to ignore it, you can hide specific warnings
    
  20. using the :setting:`SILENCED_SYSTEM_CHECKS` setting in your project settings file.
    
  21. 
    
  22. A full list of all checks that can be raised by Django can be found in the
    
  23. :doc:`System check reference </ref/checks>`.
    
  24. 
    
  25. Writing your own checks
    
  26. =======================
    
  27. 
    
  28. The framework is flexible and allows you to write functions that perform
    
  29. any other kind of check you may require. The following is an example stub
    
  30. check function::
    
  31. 
    
  32.     from django.core.checks import Error, register
    
  33. 
    
  34.     @register()
    
  35.     def example_check(app_configs, **kwargs):
    
  36.         errors = []
    
  37.         # ... your check logic here
    
  38.         if check_failed:
    
  39.             errors.append(
    
  40.                 Error(
    
  41.                     'an error',
    
  42.                     hint='A hint.',
    
  43.                     obj=checked_object,
    
  44.                     id='myapp.E001',
    
  45.                 )
    
  46.             )
    
  47.         return errors
    
  48. 
    
  49. The check function *must* accept an ``app_configs`` argument; this argument is
    
  50. the list of applications that should be inspected. If ``None``, the check must
    
  51. be run on *all* installed apps in the project.
    
  52. 
    
  53. The check will receive a ``databases`` keyword argument. This is a list of
    
  54. database aliases whose connections may be used to inspect database level
    
  55. configuration. If ``databases`` is ``None``, the check must not use any
    
  56. database connections.
    
  57. 
    
  58. The ``**kwargs`` argument is required for future expansion.
    
  59. 
    
  60. Messages
    
  61. --------
    
  62. 
    
  63. The function must return a list of messages. If no problems are found as a result
    
  64. of the check, the check function must return an empty list.
    
  65. 
    
  66. The warnings and errors raised by the check method must be instances of
    
  67. :class:`~django.core.checks.CheckMessage`. An instance of
    
  68. :class:`~django.core.checks.CheckMessage` encapsulates a single reportable
    
  69. error or warning. It also provides context and hints applicable to the
    
  70. message, and a unique identifier that is used for filtering purposes.
    
  71. 
    
  72. The concept is very similar to messages from the :doc:`message framework
    
  73. </ref/contrib/messages>` or the :doc:`logging framework </topics/logging>`.
    
  74. Messages are tagged with a ``level`` indicating the severity of the message.
    
  75. 
    
  76. There are also shortcuts to make creating messages with common levels easier.
    
  77. When using these classes you can omit the ``level`` argument because it is
    
  78. implied by the class name.
    
  79. 
    
  80. * :class:`Debug`
    
  81. * :class:`Info`
    
  82. * :class:`Warning`
    
  83. * :class:`Error`
    
  84. * :class:`Critical`
    
  85. 
    
  86. .. _registering-labeling-checks:
    
  87. 
    
  88. Registering and labeling checks
    
  89. -------------------------------
    
  90. 
    
  91. Lastly, your check function must be registered explicitly with system check
    
  92. registry. Checks should be registered in a file that's loaded when your
    
  93. application is loaded; for example, in the :meth:`AppConfig.ready()
    
  94. <django.apps.AppConfig.ready>` method.
    
  95. 
    
  96. .. function:: register(*tags)(function)
    
  97. 
    
  98. You can pass as many tags to ``register`` as you want in order to label your
    
  99. check. Tagging checks is useful since it allows you to run only a certain
    
  100. group of checks. For example, to register a compatibility check, you would
    
  101. make the following call::
    
  102. 
    
  103.     from django.core.checks import register, Tags
    
  104. 
    
  105.     @register(Tags.compatibility)
    
  106.     def my_check(app_configs, **kwargs):
    
  107.         # ... perform compatibility checks and collect errors
    
  108.         return errors
    
  109. 
    
  110. You can register "deployment checks" that are only relevant to a production
    
  111. settings file like this::
    
  112. 
    
  113.     @register(Tags.security, deploy=True)
    
  114.     def my_check(app_configs, **kwargs):
    
  115.         ...
    
  116. 
    
  117. These checks will only be run if the :option:`check --deploy` option is used.
    
  118. 
    
  119. You can also use ``register`` as a function rather than a decorator by
    
  120. passing a callable object (usually a function) as the first argument
    
  121. to ``register``.
    
  122. 
    
  123. The code below is equivalent to the code above::
    
  124. 
    
  125.     def my_check(app_configs, **kwargs):
    
  126.         ...
    
  127.     register(my_check, Tags.security, deploy=True)
    
  128. 
    
  129. .. _field-checking:
    
  130. 
    
  131. Field, model, manager, and database checks
    
  132. ------------------------------------------
    
  133. 
    
  134. In some cases, you won't need to register your check function -- you can
    
  135. piggyback on an existing registration.
    
  136. 
    
  137. Fields, models, model managers, and database backends all implement a
    
  138. ``check()`` method that is already registered with the check framework. If you
    
  139. want to add extra checks, you can extend the implementation on the base class,
    
  140. perform any extra checks you need, and append any messages to those generated
    
  141. by the base class. It's recommended that you delegate each check to separate
    
  142. methods.
    
  143. 
    
  144. Consider an example where you are implementing a custom field named
    
  145. ``RangedIntegerField``. This field adds ``min`` and ``max`` arguments to the
    
  146. constructor of ``IntegerField``. You may want to add a check to ensure that users
    
  147. provide a min value that is less than or equal to the max value. The following
    
  148. code snippet shows how you can implement this check::
    
  149. 
    
  150.     from django.core import checks
    
  151.     from django.db import models
    
  152. 
    
  153.     class RangedIntegerField(models.IntegerField):
    
  154.         def __init__(self, min=None, max=None, **kwargs):
    
  155.             super().__init__(**kwargs)
    
  156.             self.min = min
    
  157.             self.max = max
    
  158. 
    
  159.         def check(self, **kwargs):
    
  160.             # Call the superclass
    
  161.             errors = super().check(**kwargs)
    
  162. 
    
  163.             # Do some custom checks and add messages to `errors`:
    
  164.             errors.extend(self._check_min_max_values(**kwargs))
    
  165. 
    
  166.             # Return all errors and warnings
    
  167.             return errors
    
  168. 
    
  169.         def _check_min_max_values(self, **kwargs):
    
  170.             if (self.min is not None and
    
  171.                     self.max is not None and
    
  172.                     self.min > self.max):
    
  173.                 return [
    
  174.                     checks.Error(
    
  175.                         'min greater than max.',
    
  176.                         hint='Decrease min or increase max.',
    
  177.                         obj=self,
    
  178.                         id='myapp.E001',
    
  179.                     )
    
  180.                 ]
    
  181.             # When no error, return an empty list
    
  182.             return []
    
  183. 
    
  184. If you wanted to add checks to a model manager, you would take the same
    
  185. approach on your subclass of :class:`~django.db.models.Manager`.
    
  186. 
    
  187. If you want to add a check to a model class, the approach is *almost* the same:
    
  188. the only difference is that the check is a classmethod, not an instance method::
    
  189. 
    
  190.     class MyModel(models.Model):
    
  191.         @classmethod
    
  192.         def check(cls, **kwargs):
    
  193.             errors = super().check(**kwargs)
    
  194.             # ... your own checks ...
    
  195.             return errors
    
  196. 
    
  197. Writing tests
    
  198. -------------
    
  199. 
    
  200. Messages are comparable. That allows you to easily write tests::
    
  201. 
    
  202.     from django.core.checks import Error
    
  203.     errors = checked_object.check()
    
  204.     expected_errors = [
    
  205.         Error(
    
  206.             'an error',
    
  207.             hint='A hint.',
    
  208.             obj=checked_object,
    
  209.             id='myapp.E001',
    
  210.         )
    
  211.     ]
    
  212.     self.assertEqual(errors, expected_errors)