summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/howto/custom-management-commands.txt32
-rw-r--r--docs/index.txt1
-rw-r--r--docs/internals/deprecation.txt10
-rw-r--r--docs/intro/tutorial01.txt6
-rw-r--r--docs/ref/checks.txt208
-rw-r--r--docs/ref/django-admin.txt41
-rw-r--r--docs/ref/index.txt1
-rw-r--r--docs/ref/settings.txt17
-rw-r--r--docs/releases/1.7.txt42
-rw-r--r--docs/topics/db/models.txt4
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`::