diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/howto/custom-management-commands.txt | 32 | ||||
| -rw-r--r-- | docs/index.txt | 1 | ||||
| -rw-r--r-- | docs/internals/deprecation.txt | 10 | ||||
| -rw-r--r-- | docs/intro/tutorial01.txt | 6 | ||||
| -rw-r--r-- | docs/ref/checks.txt | 208 | ||||
| -rw-r--r-- | docs/ref/django-admin.txt | 41 | ||||
| -rw-r--r-- | docs/ref/index.txt | 1 | ||||
| -rw-r--r-- | docs/ref/settings.txt | 17 | ||||
| -rw-r--r-- | docs/releases/1.7.txt | 42 | ||||
| -rw-r--r-- | docs/topics/db/models.txt | 4 |
10 files changed, 343 insertions, 19 deletions
diff --git a/docs/howto/custom-management-commands.txt b/docs/howto/custom-management-commands.txt index b5d461e2ce..42dd4bfc06 100644 --- a/docs/howto/custom-management-commands.txt +++ b/docs/howto/custom-management-commands.txt @@ -227,8 +227,23 @@ All attributes can be set in your derived class and can be used in wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is ``False``. +.. attribute:: BaseCommand.requires_system_checks + +.. versionadded:: 1.7 + + A boolean; if ``True``, the entire Django project will be checked for + potential problems prior to executing the command. If + ``requires_system_checks`` is missing, the value of + ``requires_model_validation`` is used. If the latter flag is missing + as well, the default value (``True``) is used. Defining both + ``requires_system_checks`` and ``requires_model_validation`` will result + in an error. + .. attribute:: BaseCommand.requires_model_validation +.. deprecated:: 1.7 + Replaced by ``requires_system_checks`` + A boolean; if ``True``, validation of installed models will be performed prior to executing the command. Default value is ``True``. To validate an individual application's models @@ -299,12 +314,23 @@ the :meth:`~BaseCommand.handle` method must be implemented. The actual logic of the command. Subclasses must implement this method. -.. method:: BaseCommand.validate(app=None, display_num_errors=False) +.. method:: BaseCommand.check(app_configs=None, tags=None, display_num_errors=False) - Validates the given app, raising :class:`CommandError` for any errors. +.. versionadded:: 1.7 + + Uses the system check framework to inspect the entire Django project for + potential problems. Serious problems are raised as a :class:`CommandError`; + warnings are output to stderr; minor notifications are output to stdout. + + If ``apps`` and ``tags`` are both None, all system checks are performed. + ``tags`` can be a list of check tags, like ``compatibility`` or ``models``. + +.. method:: BaseCommand.validate(app=None, display_num_errors=False) - If ``app`` is None, then all installed apps are validated. +.. deprecated:: 1.7 + Replaced with the :djadmin:`check` command + If ``app`` is None, then all installed apps are checked for errors. .. _ref-basecommand-subclasses: diff --git a/docs/index.txt b/docs/index.txt index 1856beb65e..cf907df335 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -291,6 +291,7 @@ Learn about some other core functionalities of the Django framework: * :doc:`Flatpages <ref/contrib/flatpages>` * :doc:`Redirects <ref/contrib/redirects>` * :doc:`Signals <topics/signals>` +* :doc:`System check framework <ref/checks>` * :doc:`The sites framework <ref/contrib/sites>` * :doc:`Unicode in Django <ref/unicode>` diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 34e974cea3..d8d0110a74 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -234,6 +234,16 @@ these changes. * Passing callable arguments to querysets will no longer be possible. +* ``BaseCommand.requires_model_validation`` will be removed in favor of + ``requires_system_checks``. Admin validators will be replaced by admin + checks. + +* ``ModelAdmin.validator`` will be removed in favor of the new ``checks`` + attribute. + +* ``django.db.backends.DatabaseValidation.validate_field`` will be removed in + favor of the ``check_field`` method. + 2.0 --- diff --git a/docs/intro/tutorial01.txt b/docs/intro/tutorial01.txt index e79535661c..1bf11e47ae 100644 --- a/docs/intro/tutorial01.txt +++ b/docs/intro/tutorial01.txt @@ -140,7 +140,7 @@ You'll see the following output on the command line: .. parsed-literal:: - Validating models... + Performing system checks... 0 errors found |today| - 15:50:53 @@ -545,8 +545,8 @@ Note the following: changes. If you're interested, you can also run -:djadmin:`python manage.py validate <validate>`; this checks for any errors in -your models without making migrations or touching the database. +:djadmin:`python manage.py check <check>`; this checks for any problems in +your project without making migrations or touching the database. Now, run :djadmin:`migrate` again to create those model tables in your database: diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt new file mode 100644 index 0000000000..0a10c753a3 --- /dev/null +++ b/docs/ref/checks.txt @@ -0,0 +1,208 @@ +====================== +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 implemenation 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 sublass 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 diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 06f589ee63..29c6bffb9e 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -95,18 +95,36 @@ documentation for the :djadminopt:`--verbosity` option. Available commands ================== -check ------ +check <appname appname ...> +--------------------------- .. django-admin:: check -.. versionadded:: 1.6 +.. versionchanged:: 1.7 + +Uses the :doc:`system check framework </ref/checks>` to inspect +the entire Django project for common problems. + +The system check framework will confirm that there aren't any problems with +your installed models or your admin registrations. It will also provide warnings +of common compatibility problems introduced by upgrading Django to a new version. +Custom checks may be introduced by other libraries and applications. -Performs a series of checks to verify a given setup (settings/application code) -is compatible with the current version of Django. +By default, all apps will be checkd. You can check a subset of apps by providing +a list of app labels as arguments:: -Upon finding things that are incompatible or require notifying the user, it -issues a series of warnings. + python manage.py auth admin myapp + +If you do not specify any app, all apps will be checked. + +.. django-admin-option:: --tag <tagname> + +The :doc:`system check framework </ref/checks>` performs many different +types of checks. These check types are categorized with tags. You can use these tags +to restrict the checks performed to just those in a particular category. For example, +to perform only security and compatibility checks, you would run:: + + python manage.py --tag security -tag compatibility compilemessages --------------- @@ -810,9 +828,9 @@ reduction. ``pyinotify`` support was added. When you start the server, and each time you change Python code while the -server is running, the server will validate all of your installed models. (See -the :djadmin:`validate` command below.) If the validator finds errors, it will -print them to standard output, but it won't stop the server. +server is running, the server will check your entire Django project for errors (see +the :djadmin:`check` command). If any errors are found, they will be printed +to standard output, but it won't stop the server. You can run as many servers as you want, as long as they're on separate ports. Just execute ``django-admin.py runserver`` more than once. @@ -1310,6 +1328,9 @@ validate .. django-admin:: validate +.. deprecated:: 1.7 + Replaced by the :djadmin:`check` command. + Validates all installed models (according to the :setting:`INSTALLED_APPS` setting) and prints validation errors to standard output. diff --git a/docs/ref/index.txt b/docs/ref/index.txt index 6d7bfd4da4..0b2f3ab3eb 100644 --- a/docs/ref/index.txt +++ b/docs/ref/index.txt @@ -6,6 +6,7 @@ API Reference :maxdepth: 1 applications + checks class-based-views/index clickjacking contrib/index diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index e7ee4013c2..d3fc66b8e1 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -1766,6 +1766,22 @@ The backend used for signing cookies and other data. See also the :doc:`/topics/signing` documentation. +.. setting:: SILENCED_SYSTEM_CHECKS + +SILENCED_SYSTEM_CHECKS +---------------------- + +.. versionadded:: 1.7 + +Default: ``[]`` + +A list of identifers of messages generated by the system check framework +(i.e. ``["models.W001"]``) that you wish to permanently acknowledge and ignore. +Silenced warnings will no longer be output to the console; silenced errors +will still be printed, but will not prevent management commands from running. + +See also the :doc:`/ref/checks` documentation. + .. setting:: TEMPLATE_CONTEXT_PROCESSORS TEMPLATE_CONTEXT_PROCESSORS @@ -2737,6 +2753,7 @@ Error reporting * :setting:`IGNORABLE_404_URLS` * :setting:`MANAGERS` * :setting:`SEND_BROKEN_LINK_EMAILS` +* :setting:`SILENCED_SYSTEM_CHECKS` File uploads ------------ diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index 7d58f7a7c8..34b69e3e83 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -140,6 +140,17 @@ Using a custom manager when traversing reverse relations It is now possible to :ref:`specify a custom manager <using-custom-reverse-manager>` when traversing a reverse relationship. +New system check framework +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We've added a new :doc:`System check framework </ref/checks>` for +detecting common problems (like invalid models) and providing hints for +resolving those problems. The framework is extensible so you can add your +own checks for your own apps and libraries. + +To perform system checks, you use the :djadmin:`check` management command. +This command replaces the older :djadmin:`validate` management command. + New ``Prefetch`` object for advanced ``prefetch_related`` operations. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -993,7 +1004,7 @@ considered a bug and has been addressed. ``syncdb`` ~~~~~~~~~~ -The ``syncdb`` command has been deprecated in favour of the new ``migrate`` +The :djadmin:`syncdb` command has been deprecated in favor of the new :djadmin:`migrate` command. ``migrate`` takes the same arguments as ``syncdb`` used to plus a few more, so it's safe to just change the name you're calling and nothing else. @@ -1103,3 +1114,32 @@ remove the setting from your configuration at your convenience. ``SplitDateTimeWidget`` support in :class:`~django.forms.DateTimeField` is deprecated, use ``SplitDateTimeWidget`` with :class:`~django.forms.SplitDateTimeField` instead. + +``validate`` +~~~~~~~~~~~~ + +:djadmin:`validate` command is deprecated in favor of :djadmin:`check` command. + +``django.core.management.BaseCommand`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``requires_model_validation`` is deprecated in favor of a new +``requires_system_checks`` flag. If the latter flag is missing, then the +value of the former flag is used. Defining both ``requires_system_checks`` and +``requires_model_validation`` results in an error. + +The ``check()`` method has replaced the old ``validate()`` method. + +``ModelAdmin.validator`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +``ModelAdmin.validator`` is deprecated in favor of new ``checks`` attribute. + +``django.db.backends.DatabaseValidation.validate_field`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This method is deprecated in favor of a new ``check_field`` method. +The functionality required by ``check_field()`` is the same as that provided +by ``validate_field()``, but the output format is different. Third-party database +backends needing this functionality should modify their backends to provide an +implementation of ``check_field()``. diff --git a/docs/topics/db/models.txt b/docs/topics/db/models.txt index 1138f12fb2..51fa51194a 100644 --- a/docs/topics/db/models.txt +++ b/docs/topics/db/models.txt @@ -960,7 +960,7 @@ The reverse name of the ``common.ChildA.m2m`` field will be reverse name of the ``rare.ChildB.m2m`` field will be ``rare_childb_related``. It is up to you how you use the ``'%(class)s'`` and ``'%(app_label)s`` portion to construct your related name, but if you forget to use it, Django will raise -errors when you validate your models (or run :djadmin:`migrate`). +errors when you perform system checks (or run :djadmin:`migrate`). If you don't specify a :attr:`~django.db.models.ForeignKey.related_name` attribute for a field in an abstract base class, the default reverse name will @@ -1053,7 +1053,7 @@ are putting those types of relations on a subclass of another model, you **must** specify the :attr:`~django.db.models.ForeignKey.related_name` attribute on each such field. If you forget, Django will raise an error when you run -:djadmin:`validate` or :djadmin:`migrate`. +:djadmin:`check` or :djadmin:`migrate`. For example, using the above ``Place`` class again, let's create another subclass with a :class:`~django.db.models.ManyToManyField`:: |
