Refs #23919 -- Removed Python 2 notes in docs.
This commit is contained in:
parent
c716fe8782
commit
f6acd1d271
|
@ -134,7 +134,6 @@ pygments_style = 'trac'
|
|||
intersphinx_mapping = {
|
||||
'python': ('https://docs.python.org/3/', None),
|
||||
'sphinx': ('http://sphinx-doc.org/', None),
|
||||
'six': ('https://pythonhosted.org/six/', None),
|
||||
'psycopg2': ('http://initd.org/psycopg/docs/', None),
|
||||
}
|
||||
|
||||
|
|
|
@ -65,18 +65,11 @@ is the last version to support Python 3.3.
|
|||
What Python version should I use with Django?
|
||||
=============================================
|
||||
|
||||
As of Django 1.6, Python 3 support is considered stable and you can safely use
|
||||
it in production. See also :doc:`/topics/python3`. However, the community is
|
||||
still in the process of migrating third-party packages and applications to
|
||||
Python 3.
|
||||
|
||||
If you're starting a new project, and the dependencies you plan to use work on
|
||||
Python 3, you should use Python 3. If they don't, consider contributing to the
|
||||
porting efforts, or stick to Python 2.
|
||||
Python 3 is recommended. Django 1.11 is the last version to support Python 2.7.
|
||||
Support for Python 2.7 and Django 1.11 ends in 2020.
|
||||
|
||||
Since newer versions of Python are often faster, have more features, and are
|
||||
better supported, all else being equal, we recommend that you use the latest
|
||||
2.x.y or 3.x.y release.
|
||||
better supported, the latest version of Python 3 is recommended.
|
||||
|
||||
You don't lose anything in Django by using an older release, but you don't take
|
||||
advantage of the improvements and optimizations in newer Python releases.
|
||||
|
|
|
@ -55,15 +55,6 @@ pitfalls producing this error:
|
|||
case, please refer to your system documentation to learn how you can change
|
||||
this to a UTF-8 locale.
|
||||
|
||||
* You created raw bytestrings, which is easy to do on Python 2::
|
||||
|
||||
my_string = 'café'
|
||||
|
||||
Either use the ``u''`` prefix or even better, add the
|
||||
``from __future__ import unicode_literals`` line at the top of your file
|
||||
so that your code will be compatible with Python 3.2 which doesn't support
|
||||
the ``u''`` prefix.
|
||||
|
||||
Related resources:
|
||||
|
||||
* :doc:`Unicode in Django </ref/unicode>`
|
||||
|
|
|
@ -26,10 +26,6 @@ directory whose name doesn't begin with an underscore. For example::
|
|||
tests.py
|
||||
views.py
|
||||
|
||||
On Python 2, be sure to include ``__init__.py`` files in both the
|
||||
``management`` and ``management/commands`` directories as done above or your
|
||||
command will not be detected.
|
||||
|
||||
In this example, the ``closepoll`` command will be made available to any project
|
||||
that includes the ``polls`` application in :setting:`INSTALLED_APPS`.
|
||||
|
||||
|
|
|
@ -704,14 +704,12 @@ smoothly:
|
|||
a field that's similar to what you want and extend it a little bit,
|
||||
instead of creating an entirely new field from scratch.
|
||||
|
||||
2. Put a ``__str__()`` (``__unicode__()`` on Python 2) method on the class you're
|
||||
wrapping up as a field. There are a lot of places where the default
|
||||
behavior of the field code is to call
|
||||
2. Put a ``__str__()`` method on the class you're wrapping up as a field. There
|
||||
are a lot of places where the default behavior of the field code is to call
|
||||
:func:`~django.utils.encoding.force_text` on the value. (In our
|
||||
examples in this document, ``value`` would be a ``Hand`` instance, not a
|
||||
``HandField``). So if your ``__str__()`` method (``__unicode__()`` on
|
||||
Python 2) automatically converts to the string form of your Python object,
|
||||
you can save yourself a lot of work.
|
||||
``HandField``). So if your ``__str__()`` method automatically converts to
|
||||
the string form of your Python object, you can save yourself a lot of work.
|
||||
|
||||
Writing a ``FileField`` subclass
|
||||
================================
|
||||
|
|
|
@ -250,19 +250,3 @@ details about the default templates:
|
|||
* :ref:`http_internal_server_error_view`
|
||||
* :ref:`http_forbidden_view`
|
||||
* :ref:`http_bad_request_view`
|
||||
|
||||
Python Options
|
||||
==============
|
||||
|
||||
It's strongly recommended that you invoke the Python process running your
|
||||
Django application using the `-R`_ option or with the :envvar:`PYTHONHASHSEED`
|
||||
environment variable set to ``random``. This option is enabled by default
|
||||
starting with Python 3.3.
|
||||
|
||||
These options help protect your site from denial-of-service (DoS)
|
||||
attacks triggered by carefully crafted inputs. Such an attack can
|
||||
drastically increase CPU usage by causing worst-case performance when
|
||||
creating ``dict`` instances. See `oCERT advisory #2011-003
|
||||
<http://www.ocert.org/advisories/ocert-2011-003.html>`_ for more information.
|
||||
|
||||
.. _-r: https://docs.python.org/2/using/cmdline.html#cmdoption-R
|
||||
|
|
|
@ -53,26 +53,6 @@ mention:
|
|||
about escaping strings with quotes or commas in them. Just pass
|
||||
``writerow()`` your raw strings, and it'll do the right thing.
|
||||
|
||||
.. admonition:: Handling Unicode on Python 2
|
||||
|
||||
Python 2's :mod:`csv` module does not support Unicode input. Since Django
|
||||
uses Unicode internally this means strings read from sources such as
|
||||
:class:`~django.http.HttpRequest` are potentially problematic. There are a
|
||||
few options for handling this:
|
||||
|
||||
* Manually encode all Unicode objects to a compatible encoding.
|
||||
|
||||
* Use the ``UnicodeWriter`` class provided in the `csv module's examples
|
||||
section`_.
|
||||
|
||||
* Use the `python-unicodecsv module`_, which aims to be a drop-in
|
||||
replacement for :mod:`csv` that gracefully handles Unicode.
|
||||
|
||||
For more information, see the Python documentation of the :mod:`csv` module.
|
||||
|
||||
.. _`csv module's examples section`: https://docs.python.org/2/library/csv.html#examples
|
||||
.. _`python-unicodecsv module`: https://github.com/jdunck/python-unicodecsv
|
||||
|
||||
.. _streaming-csv-files:
|
||||
|
||||
Streaming large CSV files
|
||||
|
@ -89,7 +69,6 @@ the assembly and transmission of a large CSV file::
|
|||
|
||||
import csv
|
||||
|
||||
from django.utils.six.moves import range
|
||||
from django.http import StreamingHttpResponse
|
||||
|
||||
class Echo(object):
|
||||
|
|
|
@ -282,7 +282,6 @@ Django aims to be compatible with multiple different flavors and versions of
|
|||
Python:
|
||||
|
||||
* :doc:`Jython support <howto/jython>`
|
||||
* :doc:`Python 3 compatibility <topics/python3>`
|
||||
|
||||
Geographic framework
|
||||
====================
|
||||
|
|
|
@ -122,8 +122,8 @@ browser.
|
|||
To measure code coverage when running the tests, you need to view that file
|
||||
over HTTP. To view code coverage:
|
||||
|
||||
* Execute ``python -m http.server`` (or ``python -m SimpleHTTPServer`` on
|
||||
Python 2) from the root directory (not from inside ``js_tests``).
|
||||
* Execute ``python -m http.server`` from the root directory (not from inside
|
||||
``js_tests``).
|
||||
* Open http://localhost:8000/js_tests/tests.html in your web browser.
|
||||
|
||||
Testing from the command line
|
||||
|
|
|
@ -31,7 +31,7 @@ Next, clone your fork, install some requirements, and run the tests::
|
|||
$ git clone git@github.com:YourGitHubName/django.git django-repo
|
||||
$ cd django-repo/tests
|
||||
$ pip install -e ..
|
||||
$ pip install -r requirements/py3.txt # Python 2: py2.txt
|
||||
$ pip install -r requirements/py3.txt
|
||||
$ ./runtests.py
|
||||
|
||||
Installing the requirements will likely require some operating system packages
|
||||
|
@ -39,8 +39,7 @@ that your computer doesn't have installed. You can usually figure out which
|
|||
package to install by doing a Web search for the last line or so of the error
|
||||
message. Try adding your operating system to the search query if needed.
|
||||
|
||||
If you have trouble installing the requirements, you can skip that step, except
|
||||
on Python 2, where you must ``pip install mock``. See
|
||||
If you have trouble installing the requirements, you can skip that step. See
|
||||
:ref:`running-unit-tests-dependencies` for details on installing the optional
|
||||
test dependencies. If you don't have an optional dependency installed, the
|
||||
tests that require it will be skipped.
|
||||
|
@ -75,9 +74,8 @@ command from any place in the Django source tree::
|
|||
By default, ``tox`` runs the test suite with the bundled test settings file for
|
||||
SQLite, ``flake8``, ``isort``, and the documentation spelling checker. In
|
||||
addition to the system dependencies noted elsewhere in this documentation,
|
||||
the commands ``python2`` and ``python3`` must be on your path and linked to
|
||||
the appropriate versions of Python. A list of default environments can be seen
|
||||
as follows::
|
||||
the command ``python3`` must be on your path and linked to the appropriate
|
||||
version of Python. A list of default environments can be seen as follows::
|
||||
|
||||
$ tox -l
|
||||
py3
|
||||
|
@ -225,7 +223,6 @@ dependencies:
|
|||
* argon2-cffi_ 16.1.0+
|
||||
* bcrypt_
|
||||
* docutils_
|
||||
* enum34_ (Python 2 only)
|
||||
* geoip2_
|
||||
* jinja2_ 2.7+
|
||||
* numpy_
|
||||
|
@ -234,7 +231,6 @@ dependencies:
|
|||
* pytz_ (required)
|
||||
* setuptools_
|
||||
* memcached_, plus a :ref:`supported Python binding <memcached>`
|
||||
* mock_ (for Python 2)
|
||||
* gettext_ (:ref:`gettext_on_windows`)
|
||||
* selenium_
|
||||
* sqlparse_
|
||||
|
@ -243,7 +239,7 @@ You can find these dependencies in `pip requirements files`_ inside the
|
|||
``tests/requirements`` directory of the Django source tree and install them
|
||||
like so::
|
||||
|
||||
$ pip install -r tests/requirements/py3.txt # Python 2: py2.txt
|
||||
$ pip install -r tests/requirements/py3.txt
|
||||
|
||||
If you encounter an error during the installation, your system might be missing
|
||||
a dependency for one or more of the Python packages. Consult the failing
|
||||
|
@ -265,7 +261,6 @@ associated tests will be skipped.
|
|||
.. _argon2-cffi: https://pypi.python.org/pypi/argon2_cffi
|
||||
.. _bcrypt: https://pypi.python.org/pypi/bcrypt
|
||||
.. _docutils: https://pypi.python.org/pypi/docutils
|
||||
.. _enum34: https://pypi.python.org/pypi/enum34
|
||||
.. _geoip2: https://pypi.python.org/pypi/geoip2
|
||||
.. _jinja2: https://pypi.python.org/pypi/jinja2
|
||||
.. _numpy: https://pypi.python.org/pypi/numpy
|
||||
|
@ -274,7 +269,6 @@ associated tests will be skipped.
|
|||
.. _pytz: https://pypi.python.org/pypi/pytz/
|
||||
.. _setuptools: https://pypi.python.org/pypi/setuptools/
|
||||
.. _memcached: http://memcached.org/
|
||||
.. _mock: https://pypi.python.org/pypi/mock
|
||||
.. _gettext: https://www.gnu.org/software/gettext/manual/gettext.html
|
||||
.. _selenium: https://pypi.python.org/pypi/selenium
|
||||
.. _sqlparse: https://pypi.python.org/pypi/sqlparse
|
||||
|
|
|
@ -70,9 +70,9 @@ probably got the answers.
|
|||
|
||||
.. admonition:: Python 3 required!
|
||||
|
||||
This tutorial assumes you are using Python 3. Get the latest version at
|
||||
`Python's download page <https://www.python.org/download/>`_ or with your
|
||||
operating system's package manager.
|
||||
The current development version of Django doesn't support Python 2.7. Get
|
||||
Python 3 at `Python's download page <https://www.python.org/download/>`_ or
|
||||
with your operating system's package manager.
|
||||
|
||||
.. admonition:: For Windows users
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ database-schema problems. Here's a quick example:
|
|||
class Reporter(models.Model):
|
||||
full_name = models.CharField(max_length=70)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.full_name
|
||||
|
||||
class Article(models.Model):
|
||||
|
@ -42,7 +42,7 @@ database-schema problems. Here's a quick example:
|
|||
content = models.TextField()
|
||||
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.headline
|
||||
|
||||
Install it
|
||||
|
|
|
@ -220,10 +220,8 @@ this. For a small app like polls, this process isn't too difficult.
|
|||
'License :: OSI Approved :: BSD License', # example license
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
# Replace these appropriately if you are stuck on Python 2.
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Topic :: Internet :: WWW/HTTP',
|
||||
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
|
||||
],
|
||||
|
|
|
@ -295,13 +295,12 @@ Methods
|
|||
|
||||
.. _namespace package:
|
||||
|
||||
Namespace packages as apps (Python 3.3+)
|
||||
----------------------------------------
|
||||
Namespace packages as apps
|
||||
--------------------------
|
||||
|
||||
Python versions 3.3 and later support Python packages without an
|
||||
``__init__.py`` file. These packages are known as "namespace packages" and may
|
||||
be spread across multiple directories at different locations on ``sys.path``
|
||||
(see :pep:`420`).
|
||||
Python packages without an ``__init__.py`` file are known as "namespace
|
||||
packages" and may be spread across multiple directories at different locations
|
||||
on ``sys.path`` (see :pep:`420`).
|
||||
|
||||
Django applications require a single base filesystem path where Django
|
||||
(depending on configuration) will search for templates, static assets,
|
||||
|
|
|
@ -45,9 +45,9 @@ Constructor arguments are:
|
|||
``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.
|
||||
field, or manager or any other object that defines a ``__str__()`` 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
|
||||
|
|
|
@ -57,7 +57,7 @@ simple news application with an ``Article`` model::
|
|||
body = models.TextField()
|
||||
status = models.CharField(max_length=1, choices=STATUS_CHOICES)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
A common task we might perform with a model like this is to update an
|
||||
|
|
|
@ -137,10 +137,8 @@ The ``register`` decorator
|
|||
|
||||
You can't use this decorator if you have to reference your model admin
|
||||
class in its ``__init__()`` method, e.g.
|
||||
``super(PersonAdmin, self).__init__(*args, **kwargs)``. If you are using
|
||||
Python 3 and don't have to worry about supporting Python 2, you can
|
||||
use ``super().__init__(*args, **kwargs)`` . Otherwise, you'll have to use
|
||||
``admin.site.register()`` instead of this decorator.
|
||||
``super(PersonAdmin, self).__init__(*args, **kwargs)``. You can use
|
||||
``super().__init__(*args, **kwargs)``.
|
||||
|
||||
Discovery of admin files
|
||||
------------------------
|
||||
|
@ -543,8 +541,7 @@ subclass::
|
|||
list_display = ('first_name', 'last_name')
|
||||
|
||||
If you don't set ``list_display``, the admin site will display a single
|
||||
column that displays the ``__str__()`` (``__unicode__()`` on Python 2)
|
||||
representation of each object.
|
||||
column that displays the ``__str__()`` representation of each object.
|
||||
|
||||
You have four possible values that can be used in ``list_display``:
|
||||
|
||||
|
@ -594,7 +591,7 @@ subclass::
|
|||
A few special cases to note about ``list_display``:
|
||||
|
||||
* If the field is a ``ForeignKey``, Django will display the
|
||||
``__str__()`` (``__unicode__()`` on Python 2) of the related object.
|
||||
``__str__()`` of the related object.
|
||||
|
||||
* ``ManyToManyField`` fields aren't supported, because that would
|
||||
entail executing a separate SQL statement for each row in the table.
|
||||
|
@ -681,9 +678,8 @@ subclass::
|
|||
class PersonAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'born_in_fifties')
|
||||
|
||||
* The ``__str__()`` (``__unicode__()`` on Python 2) method is just
|
||||
as valid in ``list_display`` as any other model method, so it's
|
||||
perfectly OK to do this::
|
||||
* The ``__str__()`` method is just as valid in ``list_display`` as any
|
||||
other model method, so it's perfectly OK to do this::
|
||||
|
||||
list_display = ('__str__', 'some_other_field')
|
||||
|
||||
|
|
|
@ -137,12 +137,11 @@ Attributes
|
|||
.. attribute:: username_validator
|
||||
|
||||
Points to a validator instance used to validate usernames. Defaults to
|
||||
:class:`validators.UnicodeUsernameValidator` on Python 3 and
|
||||
:class:`validators.ASCIIUsernameValidator` on Python 2.
|
||||
:class:`validators.UnicodeUsernameValidator`.
|
||||
|
||||
To change the default username validator, you can subclass the ``User``
|
||||
model and set this attribute to a different validator instance. For
|
||||
example, to use ASCII usernames on Python 3::
|
||||
example, to use ASCII usernames::
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.validators import ASCIIUsernameValidator
|
||||
|
@ -390,14 +389,12 @@ Validators
|
|||
.. class:: validators.ASCIIUsernameValidator
|
||||
|
||||
A field validator allowing only ASCII letters, in addition to ``@``, ``.``,
|
||||
``+``, ``-``, and ``_``. The default validator for ``User.username`` on
|
||||
Python 2.
|
||||
``+``, ``-``, and ``_``.
|
||||
|
||||
.. class:: validators.UnicodeUsernameValidator
|
||||
|
||||
A field validator allowing Unicode letters, in addition to ``@``, ``.``,
|
||||
``+``, ``-``, and ``_``. The default validator for ``User.username`` on
|
||||
Python 3.
|
||||
``+``, ``-``, and ``_``. The default validator for ``User.username``.
|
||||
|
||||
.. _topics-auth-signals:
|
||||
|
||||
|
|
|
@ -251,7 +251,7 @@ A simple example is a tagging system, which might look like this::
|
|||
object_id = models.PositiveIntegerField()
|
||||
content_object = GenericForeignKey('content_type', 'object_id')
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.tag
|
||||
|
||||
A normal :class:`~django.db.models.ForeignKey` can only "point
|
||||
|
|
|
@ -63,8 +63,8 @@ of using ``ogrinspect`` :ref:`in the tutorial <ogrinspect-intro>`.
|
|||
|
||||
.. django-admin-option:: --name-field NAME_FIELD
|
||||
|
||||
Generates a ``__str__`` routine (``__unicode__`` on Python 2) on the model
|
||||
that will return the given field name.
|
||||
Generates a ``__str__()`` method on the model that returns the given field
|
||||
name.
|
||||
|
||||
.. django-admin-option:: --no-imports
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ Example
|
|||
name = models.CharField(max_length=25) # corresponds to the 'str' field
|
||||
poly = models.PolygonField(srid=4269) # we want our model in a different SRID
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return 'Name: %s' % self.name
|
||||
|
||||
3. Use :class:`LayerMapping` to extract all the features and place them in the
|
||||
|
|
|
@ -216,7 +216,7 @@ model to represent this data::
|
|||
mpoly = models.MultiPolygonField()
|
||||
|
||||
# Returns the string representation of the model.
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
Note that the ``models`` module is imported from ``django.contrib.gis.db``.
|
||||
|
|
|
@ -104,7 +104,7 @@ We will use the following example model::
|
|||
name = models.CharField(max_length=200)
|
||||
tags = ArrayField(models.CharField(max_length=200), blank=True)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
.. fieldlookup:: arrayfield.contains
|
||||
|
@ -313,7 +313,7 @@ We will use the following example model::
|
|||
name = models.CharField(max_length=200)
|
||||
data = HStoreField()
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
.. fieldlookup:: hstorefield.key
|
||||
|
@ -521,7 +521,7 @@ We will use the following example model::
|
|||
name = models.CharField(max_length=200)
|
||||
data = JSONField()
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
.. fieldlookup:: jsonfield.key
|
||||
|
@ -680,7 +680,7 @@ model::
|
|||
ages = IntegerRangeField()
|
||||
start = models.DateTimeField()
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
We will also use the following example objects::
|
||||
|
|
|
@ -273,24 +273,18 @@ running ``migrate``::
|
|||
MySQL DB API Drivers
|
||||
--------------------
|
||||
|
||||
The Python Database API is described in :pep:`249`. MySQL has three prominent
|
||||
drivers that implement this API:
|
||||
MySQL has a couple drivers that implement the Python Database API described in
|
||||
:pep:`249`:
|
||||
|
||||
- `MySQLdb`_ is a native driver that has been developed and supported for over
|
||||
a decade by Andy Dustman.
|
||||
- `mysqlclient`_ is a fork of ``MySQLdb`` which notably supports Python 3 and
|
||||
can be used as a drop-in replacement for MySQLdb. At the time of this writing,
|
||||
this is **the recommended choice** for using MySQL with Django.
|
||||
- `mysqlclient`_ is a native driver. It's **the recommended choice**.
|
||||
- `MySQL Connector/Python`_ is a pure Python driver from Oracle that does not
|
||||
require the MySQL client library or any Python modules outside the standard
|
||||
library.
|
||||
|
||||
.. _MySQLdb: https://pypi.python.org/pypi/MySQL-python/1.2.4
|
||||
.. _mysqlclient: https://pypi.python.org/pypi/mysqlclient
|
||||
.. _MySQL Connector/Python: https://dev.mysql.com/downloads/connector/python
|
||||
|
||||
All these drivers are thread-safe and provide connection pooling. ``MySQLdb``
|
||||
is the only one not supporting Python 3 currently.
|
||||
All these drivers are thread-safe and provide connection pooling.
|
||||
|
||||
In addition to a DB API driver, Django needs an adapter to access the database
|
||||
drivers from its ORM. Django provides an adapter for MySQLdb/mysqlclient while
|
||||
|
@ -298,30 +292,10 @@ MySQL Connector/Python includes `its own`_.
|
|||
|
||||
.. _its own: https://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html
|
||||
|
||||
MySQLdb
|
||||
~~~~~~~
|
||||
|
||||
Django requires MySQLdb version 1.2.1p2 or later.
|
||||
|
||||
At the time of writing, the latest release of MySQLdb (1.2.5) doesn't support
|
||||
Python 3. In order to use MySQLdb under Python 3, you'll have to install
|
||||
``mysqlclient`` instead.
|
||||
|
||||
.. note::
|
||||
There are known issues with the way MySQLdb converts date strings into
|
||||
datetime objects. Specifically, date strings with value ``0000-00-00`` are
|
||||
valid for MySQL but will be converted into ``None`` by MySQLdb.
|
||||
|
||||
This means you should be careful while using :djadmin:`loaddata` and
|
||||
:djadmin:`dumpdata` with rows that may have ``0000-00-00`` values, as they
|
||||
will be converted to ``None``.
|
||||
|
||||
mysqlclient
|
||||
~~~~~~~~~~~
|
||||
|
||||
Django requires `mysqlclient`_ 1.3.3 or later. Note that Python 3.2 is not
|
||||
supported. Except for the Python 3.3+ support, mysqlclient should mostly behave
|
||||
the same as MySQLDB.
|
||||
Django requires `mysqlclient`_ 1.3.3 or later.
|
||||
|
||||
MySQL Connector/Python
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -689,23 +663,6 @@ substring filtering.
|
|||
|
||||
.. _documented at sqlite.org: https://www.sqlite.org/faq.html#q18
|
||||
|
||||
Old SQLite and ``CASE`` expressions
|
||||
-----------------------------------
|
||||
|
||||
SQLite 3.6.23.1 and older contains a bug when `handling query parameters`_ in
|
||||
a ``CASE`` expression that contains an ``ELSE`` and arithmetic.
|
||||
|
||||
SQLite 3.6.23.1 was released in March 2010, and most current binary
|
||||
distributions for different platforms include a newer version of SQLite, with
|
||||
the notable exception of the Python 2.7 installers for Windows.
|
||||
|
||||
As of this writing, the latest release for Windows - Python 2.7.10 - includes
|
||||
SQLite 3.6.21. You can install ``pysqlite2`` or replace ``sqlite3.dll`` (by
|
||||
default installed in ``C:\Python27\DLLs``) with a newer version from
|
||||
https://www.sqlite.org/ to remedy this issue.
|
||||
|
||||
.. _handling query parameters: https://code.djangoproject.com/ticket/24148
|
||||
|
||||
.. _using-newer-versions-of-pysqlite:
|
||||
|
||||
Using newer versions of the SQLite DB-API 2.0 driver
|
||||
|
|
|
@ -217,11 +217,7 @@ Specification v2.0, for further information.
|
|||
|
||||
As per :pep:`3134`, a ``__cause__`` attribute is set with the original
|
||||
(underlying) database exception, allowing access to any additional
|
||||
information provided. (Note that this attribute is available under
|
||||
both Python 2 and Python 3, although :pep:`3134` normally only applies
|
||||
to Python 3. To avoid unexpected differences with Python 3, Django will also
|
||||
ensure that the exception made available via ``__cause__`` has a usable
|
||||
``__traceback__`` attribute.)
|
||||
information provided.
|
||||
|
||||
.. exception:: models.ProtectedError
|
||||
|
||||
|
|
|
@ -97,8 +97,7 @@ The ``File`` class
|
|||
|
||||
.. versionchanged:: 1.11
|
||||
|
||||
The ``readable()`` and ``writable()`` methods were added and the
|
||||
``seekable()`` method was made available on Python 2.
|
||||
The ``readable()`` and ``writable()`` methods were added.
|
||||
|
||||
.. currentmodule:: django.core.files.base
|
||||
|
||||
|
|
|
@ -810,12 +810,11 @@ Customizing the error list format
|
|||
|
||||
By default, forms use ``django.forms.utils.ErrorList`` to format validation
|
||||
errors. If you'd like to use an alternate class for displaying errors, you can
|
||||
pass that in at construction time (replace ``__str__`` by ``__unicode__`` on
|
||||
Python 2)::
|
||||
pass that in at construction time::
|
||||
|
||||
>>> from django.forms.utils import ErrorList
|
||||
>>> class DivErrorList(ErrorList):
|
||||
... def __str__(self): # __unicode__ on Python 2
|
||||
... def __str__(self):
|
||||
... return self.as_divs()
|
||||
... def as_divs(self):
|
||||
... if not self: return ''
|
||||
|
@ -840,8 +839,7 @@ they're not the only way a form object can be displayed.
|
|||
Used to display HTML or access attributes for a single field of a
|
||||
:class:`Form` instance.
|
||||
|
||||
The ``__str__()`` (``__unicode__`` on Python 2) method of this
|
||||
object displays the HTML for this field.
|
||||
The ``__str__()`` method of this object displays the HTML for this field.
|
||||
|
||||
To retrieve a single ``BoundField``, use dictionary lookup syntax on your form
|
||||
using the field's name as the key::
|
||||
|
|
|
@ -1183,12 +1183,11 @@ method::
|
|||
...
|
||||
</select>
|
||||
|
||||
The ``__str__`` (``__unicode__`` on Python 2) method of the model will be
|
||||
called to generate string representations of the objects for use in the
|
||||
field's choices; to provide customized representations, subclass
|
||||
``ModelChoiceField`` and override ``label_from_instance``. This method will
|
||||
receive a model object, and should return a string suitable for representing
|
||||
it. For example::
|
||||
The ``__str__()`` method of the model will be called to generate string
|
||||
representations of the objects for use in the field's choices. To provide
|
||||
customized representations, subclass ``ModelChoiceField`` and override
|
||||
``label_from_instance``. This method will receive a model object and should
|
||||
return a string suitable for representing it. For example::
|
||||
|
||||
from django.forms import ModelChoiceField
|
||||
|
||||
|
|
|
@ -1002,7 +1002,7 @@ For example, suppose you have these models::
|
|||
name = models.CharField(max_length=50)
|
||||
toppings = models.ManyToManyField(Topping)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return "%s (%s)" % (
|
||||
self.name,
|
||||
", ".join(topping.name for topping in self.toppings.all()),
|
||||
|
|
|
@ -480,21 +480,6 @@ a subclass of dictionary. Exceptions are outlined here:
|
|||
>>> q.items()
|
||||
[('a', '3')]
|
||||
|
||||
.. method:: QueryDict.iteritems()
|
||||
|
||||
Just like the standard dictionary ``iteritems()`` method. Like
|
||||
:meth:`QueryDict.items()` this uses the same last-value logic as
|
||||
:meth:`QueryDict.__getitem__()`.
|
||||
|
||||
Available only on Python 2.
|
||||
|
||||
.. method:: QueryDict.iterlists()
|
||||
|
||||
Like :meth:`QueryDict.iteritems()` except it includes all values, as a list,
|
||||
for each member of the dictionary.
|
||||
|
||||
Available only on Python 2.
|
||||
|
||||
.. method:: QueryDict.values()
|
||||
|
||||
Just like the standard dictionary ``values()`` method, except this uses the
|
||||
|
@ -504,12 +489,6 @@ a subclass of dictionary. Exceptions are outlined here:
|
|||
>>> q.values()
|
||||
['3']
|
||||
|
||||
.. method:: QueryDict.itervalues()
|
||||
|
||||
Just like :meth:`QueryDict.values()`, except an iterator.
|
||||
|
||||
Available only on Python 2.
|
||||
|
||||
In addition, ``QueryDict`` has the following methods:
|
||||
|
||||
.. method:: QueryDict.copy()
|
||||
|
|
|
@ -105,13 +105,13 @@ Use a dot (``.``) to access attributes of a variable.
|
|||
override dictionary lookup. For example, consider the following code snippet
|
||||
that attempts to loop over a ``collections.defaultdict``::
|
||||
|
||||
{% for k, v in defaultdict.iteritems %}
|
||||
{% for k, v in defaultdict.items %}
|
||||
Do something with k and v here...
|
||||
{% endfor %}
|
||||
|
||||
Because dictionary lookup happens first, that behavior kicks in and provides
|
||||
a default value instead of using the intended ``.iteritems()``
|
||||
method. In this case, consider converting to a dictionary first.
|
||||
a default value instead of using the intended ``.items()`` method. In this
|
||||
case, consider converting to a dictionary first.
|
||||
|
||||
In the above example, ``{{ section.title }}`` will be replaced with the
|
||||
``title`` attribute of the ``section`` object.
|
||||
|
|
|
@ -48,29 +48,7 @@ General string handling
|
|||
|
||||
Whenever you use strings with Django -- e.g., in database lookups, template
|
||||
rendering or anywhere else -- you have two choices for encoding those strings.
|
||||
You can use Unicode strings, or you can use normal strings (sometimes called
|
||||
"bytestrings") that are encoded using UTF-8.
|
||||
|
||||
In Python 3, the logic is reversed, that is normal strings are Unicode, and
|
||||
when you want to specifically create a bytestring, you have to prefix the
|
||||
string with a 'b'. As we are doing in Django code from version 1.5,
|
||||
we recommend that you import ``unicode_literals`` from the __future__ library
|
||||
in your code. Then, when you specifically want to create a bytestring literal,
|
||||
prefix the string with 'b'.
|
||||
|
||||
Python 2 legacy::
|
||||
|
||||
my_string = "This is a bytestring"
|
||||
my_unicode = u"This is an Unicode string"
|
||||
|
||||
Python 2 with unicode literals or Python 3::
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
my_string = b"This is a bytestring"
|
||||
my_unicode = "This is an Unicode string"
|
||||
|
||||
See also :doc:`Python 3 compatibility </topics/python3>`.
|
||||
You can use normal Unicode strings or bytestrings (starting with a 'b').
|
||||
|
||||
.. warning::
|
||||
|
||||
|
@ -114,7 +92,7 @@ imported.
|
|||
Normally, you won't have to worry about lazy translations. Just be aware that
|
||||
if you examine an object and it claims to be a
|
||||
``django.utils.functional.__proxy__`` object, it is a lazy translation.
|
||||
Calling ``unicode()`` with the lazy translation as the argument will generate a
|
||||
Calling ``str()`` with the lazy translation as the argument will generate a
|
||||
Unicode string in the current locale.
|
||||
|
||||
For more details about lazy translation objects, refer to the
|
||||
|
@ -140,12 +118,9 @@ for converting back and forth between Unicode and bytestrings.
|
|||
``strings_only`` parameter, if set to True, will result in Python
|
||||
numbers, booleans and ``None`` not being converted to a string (they keep
|
||||
their original types). The ``errors`` parameter takes any of the values
|
||||
that are accepted by Python's ``unicode()`` function for its error
|
||||
that are accepted by Python's ``str()`` function for its error
|
||||
handling.
|
||||
|
||||
If you pass ``smart_text()`` an object that has a ``__unicode__``
|
||||
method, it will use that method to do the conversion.
|
||||
|
||||
* ``force_text(s, encoding='utf-8', strings_only=False,
|
||||
errors='strict')`` is identical to ``smart_text()`` in almost all
|
||||
cases. The difference is when the first argument is a :ref:`lazy
|
||||
|
@ -292,8 +267,6 @@ You can pass either Unicode strings or UTF-8 bytestrings as arguments to
|
|||
``filter()`` methods and the like in the database API. The following two
|
||||
querysets are identical::
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
qs = People.objects.filter(name__contains='Å')
|
||||
qs = People.objects.filter(name__contains=b'\xc3\x85') # UTF-8 encoding of Å
|
||||
|
||||
|
@ -302,7 +275,6 @@ Templates
|
|||
|
||||
You can use either Unicode or bytestrings when creating templates manually::
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from django.template import Template
|
||||
t1 = Template(b'This is a bytestring template.')
|
||||
t2 = Template('This is a Unicode template.')
|
||||
|
@ -373,7 +345,6 @@ characters.
|
|||
The following code example demonstrates that everything except email addresses
|
||||
can be non-ASCII::
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from django.core.mail import EmailMessage
|
||||
|
||||
subject = 'My visit to Sør-Trøndelag'
|
||||
|
|
|
@ -175,9 +175,9 @@ A :class:`ResolverMatch` object can also be assigned to a triple::
|
|||
One possible use of :func:`~django.urls.resolve` would be to test whether a
|
||||
view would raise a ``Http404`` error before redirecting to it::
|
||||
|
||||
from urllib.parse import urlparse
|
||||
from django.urls import resolve
|
||||
from django.http import HttpResponseRedirect, Http404
|
||||
from django.utils.six.moves.urllib.parse import urlparse
|
||||
|
||||
def myview(request):
|
||||
next = request.META.get('HTTP_REFERER', None) or '/'
|
||||
|
|
|
@ -203,16 +203,12 @@ The functions defined in this module share the following properties:
|
|||
|
||||
.. function:: smart_text(s, encoding='utf-8', strings_only=False, errors='strict')
|
||||
|
||||
Returns a text object representing ``s`` -- ``unicode`` on Python 2 and
|
||||
``str`` on Python 3. Treats bytestrings using the ``encoding`` codec.
|
||||
Returns a ``str`` object representing ``s``. Treats bytestrings using the
|
||||
``encoding`` codec.
|
||||
|
||||
If ``strings_only`` is ``True``, don't convert (some) non-string-like
|
||||
objects.
|
||||
|
||||
.. function:: smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict')
|
||||
|
||||
Historical name of :func:`smart_text`. Only available under Python 2.
|
||||
|
||||
.. function:: is_protected_type(obj)
|
||||
|
||||
Determine if the object instance is of a protected type.
|
||||
|
@ -228,10 +224,6 @@ The functions defined in this module share the following properties:
|
|||
If ``strings_only`` is ``True``, don't convert (some) non-string-like
|
||||
objects.
|
||||
|
||||
.. function:: force_unicode(s, encoding='utf-8', strings_only=False, errors='strict')
|
||||
|
||||
Historical name of :func:`force_text`. Only available under Python 2.
|
||||
|
||||
.. function:: smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict')
|
||||
|
||||
Returns a bytestring version of ``s``, encoded as specified in
|
||||
|
@ -250,16 +242,20 @@ The functions defined in this module share the following properties:
|
|||
|
||||
.. function:: smart_str(s, encoding='utf-8', strings_only=False, errors='strict')
|
||||
|
||||
Alias of :func:`smart_bytes` on Python 2 and :func:`smart_text` on Python
|
||||
3. This function returns a ``str`` or a lazy string.
|
||||
Alias of :func:`smart_text`. This function returns a ``str`` or a lazy
|
||||
string.
|
||||
|
||||
For instance, this is suitable for writing to :data:`sys.stdout` on
|
||||
Python 2 and 3.
|
||||
For instance, this is suitable for writing to :data:`sys.stdout`.
|
||||
|
||||
Alias of :func:`smart_bytes` on Python 2 (in older versions of Django that
|
||||
support it).
|
||||
|
||||
.. function:: force_str(s, encoding='utf-8', strings_only=False, errors='strict')
|
||||
|
||||
Alias of :func:`force_bytes` on Python 2 and :func:`force_text` on Python
|
||||
3. This function always returns a ``str``.
|
||||
Alias of :func:`force_text`. This function always returns a ``str``.
|
||||
|
||||
Alias of :func:`force_bytes` on Python 2 (in older versions of Django that
|
||||
support it).
|
||||
|
||||
.. function:: iri_to_uri(iri)
|
||||
|
||||
|
@ -538,23 +534,22 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004
|
|||
|
||||
For example::
|
||||
|
||||
from django.utils import six
|
||||
from django.utils.functional import keep_lazy, keep_lazy_text
|
||||
|
||||
def fancy_utility_function(s, ...):
|
||||
# Do some conversion on string 's'
|
||||
...
|
||||
fancy_utility_function = keep_lazy(six.text_type)(fancy_utility_function)
|
||||
fancy_utility_function = keep_lazy(str)(fancy_utility_function)
|
||||
|
||||
# Or more succinctly:
|
||||
@keep_lazy(six.text_type)
|
||||
@keep_lazy(str)
|
||||
def fancy_utility_function(s, ...):
|
||||
...
|
||||
|
||||
The ``keep_lazy()`` decorator takes a number of extra arguments (``*args``)
|
||||
specifying the type(s) that the original function can return. A common
|
||||
use case is to have functions that return text. For these, you can just
|
||||
pass the ``six.text_type`` type to ``keep_lazy`` (or even simpler, use the
|
||||
pass the ``str`` type to ``keep_lazy`` (or even simpler, use the
|
||||
:func:`keep_lazy_text` decorator described in the next section).
|
||||
|
||||
Using this decorator means you can write your function and assume that the
|
||||
|
@ -563,16 +558,15 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004
|
|||
|
||||
.. function:: keep_lazy_text(func)
|
||||
|
||||
A shortcut for ``keep_lazy(six.text_type)(func)``.
|
||||
A shortcut for ``keep_lazy(str)(func)``.
|
||||
|
||||
If you have a function that returns text and you want to be able to take
|
||||
lazy arguments while delaying their evaluation, simply use this decorator::
|
||||
|
||||
from django.utils import six
|
||||
from django.utils.functional import keep_lazy, keep_lazy_text
|
||||
|
||||
# Our previous example was:
|
||||
@keep_lazy(six.text_type)
|
||||
@keep_lazy(str)
|
||||
def fancy_utility_function(s, ...):
|
||||
...
|
||||
|
||||
|
@ -680,11 +674,9 @@ escaping HTML.
|
|||
classes whose output doesn't require HTML escaping.
|
||||
|
||||
This decorator defines the ``__html__()`` method on the decorated class
|
||||
by wrapping the ``__unicode__()`` (Python 2) or ``__str__()`` (Python 3)
|
||||
in :meth:`~django.utils.safestring.mark_safe`. Ensure the ``__unicode__()``
|
||||
or ``__str__()`` method does indeed return text that doesn't require HTML
|
||||
escaping.
|
||||
|
||||
by wrapping ``__str__()`` in :meth:`~django.utils.safestring.mark_safe`.
|
||||
Ensure the ``__str__()`` method does indeed return text that doesn't
|
||||
require HTML escaping.
|
||||
|
||||
``django.utils.http``
|
||||
=====================
|
||||
|
@ -737,13 +729,11 @@ escaping HTML.
|
|||
|
||||
.. function:: base36_to_int(s)
|
||||
|
||||
Converts a base 36 string to an integer. On Python 2 the output is
|
||||
guaranteed to be an ``int`` and not a ``long``.
|
||||
Converts a base 36 string to an integer.
|
||||
|
||||
.. function:: int_to_base36(i)
|
||||
|
||||
Converts a positive integer to a base 36 string. On Python 2 ``i`` must be
|
||||
smaller than `sys.maxint`_.
|
||||
Converts a positive integer to a base 36 string.
|
||||
|
||||
.. _sys.maxint: https://docs.python.org/2/library/sys.html#sys.maxint
|
||||
|
||||
|
@ -798,17 +788,16 @@ appropriate entities.
|
|||
.. class:: SafeString
|
||||
|
||||
A ``str`` subclass that has been specifically marked as "safe"
|
||||
(requires no further escaping) for HTML output purposes. This is
|
||||
:class:`SafeBytes` on Python 2 and :class:`SafeText` on Python 3.
|
||||
(requires no further escaping) for HTML output purposes. Alias of
|
||||
:class:`SafeText`.
|
||||
|
||||
Alias of :class:`SafeBytes` on Python 2 (in older versions of Django that
|
||||
support it).
|
||||
|
||||
.. class:: SafeText
|
||||
|
||||
A ``str`` (in Python 3) or ``unicode`` (in Python 2) subclass
|
||||
that has been specifically marked as "safe" for HTML output purposes.
|
||||
|
||||
.. class:: SafeUnicode
|
||||
|
||||
Historical name of :class:`SafeText`. Only available under Python 2.
|
||||
A ``str`` subclass that has been specifically marked as "safe" for HTML
|
||||
output purposes.
|
||||
|
||||
.. function:: mark_safe(s)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ Django 1.4.11 release notes
|
|||
*April 21, 2014*
|
||||
|
||||
Django 1.4.11 fixes three security issues in 1.4.10. Additionally,
|
||||
Django's vendored version of six, :mod:`django.utils.six`, has been
|
||||
Django's vendored version of six, ``django.utils.six``, has been
|
||||
upgraded to the latest release (1.6.1).
|
||||
|
||||
Unexpected code execution using ``reverse()``
|
||||
|
|
|
@ -6,7 +6,7 @@ Django 1.4.17 release notes
|
|||
|
||||
Django 1.4.17 fixes a regression in the 1.4.14 security release.
|
||||
|
||||
Additionally, Django's vendored version of six, :mod:`django.utils.six`, has
|
||||
Additionally, Django's vendored version of six, ``django.utils.six``, has
|
||||
been upgraded to the latest release (1.9.0).
|
||||
|
||||
Bugfixes
|
||||
|
|
|
@ -64,5 +64,5 @@ Bugfixes
|
|||
========
|
||||
|
||||
* To maintain compatibility with Python 2.5, Django's vendored version of six,
|
||||
:mod:`django.utils.six`, has been downgraded to 1.8.0 which is the last
|
||||
``django.utils.six``, has been downgraded to 1.8.0 which is the last
|
||||
version to support Python 2.5.
|
||||
|
|
|
@ -113,5 +113,5 @@ Bugfixes
|
|||
``UnboundLocalError`` if :func:`~django.contrib.auth.get_user_model`
|
||||
raised an error (#21439).
|
||||
|
||||
Additionally, Django's vendored version of six, :mod:`django.utils.six`,
|
||||
Additionally, Django's vendored version of six, ``django.utils.six``,
|
||||
has been upgraded to the latest release (1.6.1).
|
||||
|
|
|
@ -107,9 +107,9 @@ to Python 3, so it's unlikely that a real-world application will have all its
|
|||
dependencies satisfied under Python 3.
|
||||
|
||||
Thus, we're recommending that Django 1.5 not be used in production under Python
|
||||
3. Instead, use this opportunity to begin :doc:`porting applications to Python 3
|
||||
</topics/python3>`. If you're an author of a pluggable component, we encourage you
|
||||
to start porting now.
|
||||
3. Instead, use this opportunity to begin porting applications to Python 3. If
|
||||
you're an author of a pluggable component, we encourage you to start porting
|
||||
now.
|
||||
|
||||
We plan to offer first-class, production-ready support for Python 3 in our next
|
||||
release, Django 1.6.
|
||||
|
|
|
@ -48,5 +48,5 @@ several bugs in 1.6.1:
|
|||
through :func:`~django.utils.safestring.mark_safe` and could end up being
|
||||
double-escaped (:ticket:`21882`).
|
||||
|
||||
Additionally, Django's vendored version of six, :mod:`django.utils.six` has been
|
||||
Additionally, Django's vendored version of six, ``django.utils.six`` has been
|
||||
upgraded to the latest release (1.5.2).
|
||||
|
|
|
@ -179,5 +179,5 @@ Other bugfixes and changes
|
|||
query to include an unnecessary join
|
||||
(:ticket:`21760`).
|
||||
|
||||
Additionally, Django's vendored version of six, :mod:`django.utils.six` has been
|
||||
Additionally, Django's vendored version of six, ``django.utils.six`` has been
|
||||
upgraded to the latest release (1.6.1).
|
||||
|
|
|
@ -6,7 +6,7 @@ Django 1.6.9 release notes
|
|||
|
||||
Django 1.6.9 fixes a regression in the 1.6.6 security release.
|
||||
|
||||
Additionally, Django's vendored version of six, :mod:`django.utils.six`, has
|
||||
Additionally, Django's vendored version of six, ``django.utils.six``, has
|
||||
been upgraded to the latest release (1.9.0).
|
||||
|
||||
Bugfixes
|
||||
|
|
|
@ -6,7 +6,7 @@ Django 1.7.2 release notes
|
|||
|
||||
Django 1.7.2 fixes several bugs in 1.7.1.
|
||||
|
||||
Additionally, Django's vendored version of six, :mod:`django.utils.six`, has
|
||||
Additionally, Django's vendored version of six, ``django.utils.six``, has
|
||||
been upgraded to the latest release (1.9.0).
|
||||
|
||||
Bugfixes
|
||||
|
|
|
@ -6,7 +6,7 @@ Django 1.8.7 release notes
|
|||
|
||||
Django 1.8.7 fixes a security issue and several bugs in 1.8.6.
|
||||
|
||||
Additionally, Django's vendored version of six, :mod:`django.utils.six`, has
|
||||
Additionally, Django's vendored version of six, ``django.utils.six``, has
|
||||
been upgraded to the latest release (1.10.0).
|
||||
|
||||
Fixed settings leak possibility in ``date`` template filter
|
||||
|
|
|
@ -1060,7 +1060,7 @@ authentication app::
|
|||
# The user is identified by their email address
|
||||
return self.email
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.email
|
||||
|
||||
def has_perm(self, perm, obj=None):
|
||||
|
|
|
@ -805,8 +805,7 @@ The basic interface is ``set(key, value, timeout)`` and ``get(key)``::
|
|||
>>> cache.get('my_key')
|
||||
'hello, world!'
|
||||
|
||||
``key`` should be a ``str`` (or ``unicode`` on Python 2), and ``value`` can be
|
||||
any picklable Python object.
|
||||
``key`` should be a ``str``, and ``value`` can be any picklable Python object.
|
||||
|
||||
The ``timeout`` argument is optional and defaults to the ``timeout`` argument
|
||||
of the appropriate backend in the :setting:`CACHES` setting (explained above).
|
||||
|
|
|
@ -87,7 +87,7 @@ We'll be using these models::
|
|||
class Meta:
|
||||
ordering = ["-name"]
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Author(models.Model):
|
||||
|
@ -96,7 +96,7 @@ We'll be using these models::
|
|||
email = models.EmailField()
|
||||
headshot = models.ImageField(upload_to='author_headshots')
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Book(models.Model):
|
||||
|
|
|
@ -17,7 +17,7 @@ objects, and a ``Publication`` has multiple ``Article`` objects:
|
|||
class Publication(models.Model):
|
||||
title = models.CharField(max_length=30)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
class Meta:
|
||||
|
@ -27,7 +27,7 @@ objects, and a ``Publication`` has multiple ``Article`` objects:
|
|||
headline = models.CharField(max_length=100)
|
||||
publications = models.ManyToManyField(Publication)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.headline
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -11,7 +11,7 @@ To define a many-to-one relationship, use :class:`~django.db.models.ForeignKey`:
|
|||
last_name = models.CharField(max_length=30)
|
||||
email = models.EmailField()
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return "%s %s" % (self.first_name, self.last_name)
|
||||
|
||||
class Article(models.Model):
|
||||
|
@ -19,7 +19,7 @@ To define a many-to-one relationship, use :class:`~django.db.models.ForeignKey`:
|
|||
pub_date = models.DateField()
|
||||
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.headline
|
||||
|
||||
class Meta:
|
||||
|
@ -64,13 +64,6 @@ Article objects have access to their related Reporter objects::
|
|||
|
||||
>>> r = a.reporter
|
||||
|
||||
On Python 2, these are strings of type ``str`` instead of unicode strings
|
||||
because that's what was used in the creation of this reporter (and we haven't
|
||||
refreshed the data from the database, which always returns unicode strings)::
|
||||
|
||||
>>> r.first_name, r.last_name
|
||||
('John', 'Smith')
|
||||
|
||||
Create an Article via the Reporter object::
|
||||
|
||||
>>> new_article = r.article_set.create(headline="John's second story", pub_date=date(2005, 7, 29))
|
||||
|
|
|
@ -13,7 +13,7 @@ In this example, a ``Place`` optionally can be a ``Restaurant``::
|
|||
name = models.CharField(max_length=50)
|
||||
address = models.CharField(max_length=80)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return "%s the place" % self.name
|
||||
|
||||
class Restaurant(models.Model):
|
||||
|
@ -25,14 +25,14 @@ In this example, a ``Place`` optionally can be a ``Restaurant``::
|
|||
serves_hot_dogs = models.BooleanField(default=False)
|
||||
serves_pizza = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return "%s the restaurant" % self.place.name
|
||||
|
||||
class Waiter(models.Model):
|
||||
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=50)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return "%s the waiter at %s" % (self.name, self.restaurant)
|
||||
|
||||
What follows are examples of operations that can be performed using the Python
|
||||
|
|
|
@ -445,14 +445,14 @@ something like this::
|
|||
class Person(models.Model):
|
||||
name = models.CharField(max_length=128)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Group(models.Model):
|
||||
name = models.CharField(max_length=128)
|
||||
members = models.ManyToManyField(Person, through='Membership')
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Membership(models.Model):
|
||||
|
@ -761,7 +761,7 @@ of :ref:`methods automatically given to each model <model-instance-methods>`.
|
|||
You can override most of these -- see `overriding predefined model methods`_,
|
||||
below -- but there are a couple that you'll almost always want to define:
|
||||
|
||||
:meth:`~Model.__str__` (Python 3)
|
||||
:meth:`~Model.__str__`
|
||||
A Python "magic method" that returns a unicode "representation" of any
|
||||
object. This is what Python and Django will use whenever a model
|
||||
instance needs to be coerced and displayed as a plain string. Most
|
||||
|
@ -771,9 +771,6 @@ below -- but there are a couple that you'll almost always want to define:
|
|||
You'll always want to define this method; the default isn't very helpful
|
||||
at all.
|
||||
|
||||
``__unicode__()`` (Python 2)
|
||||
Python 2 equivalent of ``__str__()``.
|
||||
|
||||
:meth:`~Model.get_absolute_url`
|
||||
This tells Django how to calculate the URL for an object. Django uses
|
||||
this in its admin interface, and any time it needs to figure out a URL
|
||||
|
|
|
@ -23,14 +23,14 @@ models, which comprise a Weblog application:
|
|||
name = models.CharField(max_length=100)
|
||||
tagline = models.TextField()
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Author(models.Model):
|
||||
name = models.CharField(max_length=200)
|
||||
email = models.EmailField()
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Entry(models.Model):
|
||||
|
@ -44,7 +44,7 @@ models, which comprise a Weblog application:
|
|||
n_pingbacks = models.IntegerField()
|
||||
rating = models.IntegerField()
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.headline
|
||||
|
||||
Creating objects
|
||||
|
|
|
@ -169,7 +169,7 @@ Consider this set of models::
|
|||
title = models.CharField(max_length=3, choices=TITLE_CHOICES)
|
||||
birth_date = models.DateField(blank=True, null=True)
|
||||
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Book(models.Model):
|
||||
|
|
|
@ -431,9 +431,6 @@ strings before passing them to non-Django code::
|
|||
|
||||
requests.post('https://example.com/send', data={'body': str(body)})
|
||||
|
||||
Use ``unicode`` in place of ``str`` on Python 2, or :data:`six.text_type` to
|
||||
support Python 2 and 3.
|
||||
|
||||
If you try to use a ``ugettext_lazy()`` result where a bytestring (a
|
||||
:class:`bytes` object) is expected, things won't work as expected since a
|
||||
``ugettext_lazy()`` object doesn't know how to convert itself to a bytestring.
|
||||
|
@ -534,12 +531,11 @@ For any other case where you would like to delay the translation, but have to
|
|||
pass the translatable string as argument to another function, you can wrap
|
||||
this function inside a lazy call yourself. For example::
|
||||
|
||||
from django.utils import six # Python 3 compatibility
|
||||
from django.utils.functional import lazy
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
mark_safe_lazy = lazy(mark_safe, six.text_type)
|
||||
mark_safe_lazy = lazy(mark_safe, str)
|
||||
|
||||
And then later::
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ Introductions to all the key parts of Django you'll need to know:
|
|||
i18n/index
|
||||
logging
|
||||
pagination
|
||||
python3
|
||||
security
|
||||
performance
|
||||
serialization
|
||||
|
|
|
@ -171,7 +171,7 @@ This is the recommended way to install Django.
|
|||
isolated Python environments, which are more practical than installing
|
||||
packages systemwide. They also allow installing packages without
|
||||
administrator privileges. The :doc:`contributing tutorial
|
||||
</intro/contributing>` walks through how to create a virtualenv on Python 3.
|
||||
</intro/contributing>` walks through how to create a virtualenv.
|
||||
|
||||
3. After you've created and activated a virtual environment, enter the command
|
||||
``pip install Django`` at the shell prompt.
|
||||
|
@ -227,7 +227,7 @@ latest bug fixes and improvements, follow these instructions:
|
|||
3. Make sure that the Python interpreter can load Django's code. The most
|
||||
convenient way to do this is to use virtualenv_, virtualenvwrapper_, and
|
||||
pip_. The :doc:`contributing tutorial </intro/contributing>` walks through
|
||||
how to create a virtualenv on Python 3.
|
||||
how to create a virtualenv.
|
||||
|
||||
4. After setting up and activating the virtualenv, run the following command:
|
||||
|
||||
|
|
|
@ -665,6 +665,7 @@ Django can serialize the following:
|
|||
- ``LazyObject`` instances which wrap a serializable value.
|
||||
- Any Django field
|
||||
- Any function or method reference (e.g. ``datetime.datetime.today``) (must be in module's top-level scope)
|
||||
- Unbound methods used from within the class body
|
||||
- Any class reference (must be in module's top-level scope)
|
||||
- Anything with a custom ``deconstruct()`` method (:ref:`see below <custom-deconstruct-method>`)
|
||||
|
||||
|
@ -672,31 +673,12 @@ Django can serialize the following:
|
|||
|
||||
Serialization support for ``uuid.UUID`` was added.
|
||||
|
||||
Django can serialize the following on Python 3 only:
|
||||
|
||||
- Unbound methods used from within the class body (see below)
|
||||
|
||||
Django cannot serialize:
|
||||
|
||||
- Nested classes
|
||||
- Arbitrary class instances (e.g. ``MyClass(4.3, 5.7)``)
|
||||
- Lambdas
|
||||
|
||||
Due to the fact ``__qualname__`` was only introduced in Python 3, Django can only
|
||||
serialize the following pattern (an unbound method used within the class body)
|
||||
on Python 3, and will fail to serialize a reference to it on Python 2::
|
||||
|
||||
class MyModel(models.Model):
|
||||
|
||||
def upload_to(self):
|
||||
return "something dynamic"
|
||||
|
||||
my_file = models.FileField(upload_to=upload_to)
|
||||
|
||||
If you are using Python 2, we recommend you move your methods for upload_to
|
||||
and similar arguments that accept callables (e.g. ``default``) to live in
|
||||
the main module body, rather than the class body.
|
||||
|
||||
.. _custom-deconstruct-method:
|
||||
|
||||
Adding a ``deconstruct()`` method
|
||||
|
|
|
@ -24,7 +24,7 @@ page::
|
|||
4
|
||||
>>> p.num_pages
|
||||
2
|
||||
>>> type(p.page_range) # `<type 'rangeiterator'>` in Python 2.
|
||||
>>> type(p.page_range)
|
||||
<class 'range_iterator'>
|
||||
>>> p.page_range
|
||||
range(1, 3)
|
||||
|
|
|
@ -1,369 +0,0 @@
|
|||
===================
|
||||
Porting to Python 3
|
||||
===================
|
||||
|
||||
Django 1.5 is the first version of Django to support Python 3. The same code
|
||||
runs both on Python 2 (≥ 2.6.5) and Python 3 (≥ 3.2), thanks to the six_
|
||||
compatibility layer.
|
||||
|
||||
.. _six: https://pythonhosted.org/six/
|
||||
|
||||
This document is primarily targeted at authors of pluggable applications
|
||||
who want to support both Python 2 and 3. It also describes guidelines that
|
||||
apply to Django's code.
|
||||
|
||||
Philosophy
|
||||
==========
|
||||
|
||||
This document assumes that you are familiar with the changes between Python 2
|
||||
and Python 3. If you aren't, read :ref:`Python's official porting guide
|
||||
<pyporting-howto>` first. Refreshing your knowledge of unicode handling on
|
||||
Python 2 and 3 will help; the `Pragmatic Unicode`_ presentation is a good
|
||||
resource.
|
||||
|
||||
Django uses the *Python 2/3 Compatible Source* strategy. Of course, you're
|
||||
free to chose another strategy for your own code, especially if you don't need
|
||||
to stay compatible with Python 2. But authors of pluggable applications are
|
||||
encouraged to use the same porting strategy as Django itself.
|
||||
|
||||
Writing compatible code is much easier if you target Python ≥ 2.6. Django 1.5
|
||||
introduces compatibility tools such as :mod:`django.utils.six`, which is a
|
||||
customized version of the :mod:`six module <six>`. For convenience,
|
||||
forwards-compatible aliases were introduced in Django 1.4.2. If your
|
||||
application takes advantage of these tools, it will require Django ≥ 1.4.2.
|
||||
|
||||
Obviously, writing compatible source code adds some overhead, and that can
|
||||
cause frustration. Django's developers have found that attempting to write
|
||||
Python 3 code that's compatible with Python 2 is much more rewarding than the
|
||||
opposite. Not only does that make your code more future-proof, but Python 3's
|
||||
advantages (like the saner string handling) start shining quickly. Dealing
|
||||
with Python 2 becomes a backwards compatibility requirement, and we as
|
||||
developers are used to dealing with such constraints.
|
||||
|
||||
Porting tools provided by Django are inspired by this philosophy, and it's
|
||||
reflected throughout this guide.
|
||||
|
||||
.. _Pragmatic Unicode: http://nedbatchelder.com/text/unipain.html
|
||||
|
||||
Porting tips
|
||||
============
|
||||
|
||||
Unicode literals
|
||||
----------------
|
||||
|
||||
This step consists in:
|
||||
|
||||
- Adding ``from __future__ import unicode_literals`` at the top of your Python
|
||||
modules -- it's best to put it in each and every module, otherwise you'll
|
||||
keep checking the top of your files to see which mode is in effect;
|
||||
- Removing the ``u`` prefix before unicode strings;
|
||||
- Adding a ``b`` prefix before bytestrings.
|
||||
|
||||
Performing these changes systematically guarantees backwards compatibility.
|
||||
|
||||
However, Django applications generally don't need bytestrings, since Django
|
||||
only exposes unicode interfaces to the programmer. Python 3 discourages using
|
||||
bytestrings, except for binary data or byte-oriented interfaces. Python 2
|
||||
makes bytestrings and unicode strings effectively interchangeable, as long as
|
||||
they only contain ASCII data. Take advantage of this to use unicode strings
|
||||
wherever possible and avoid the ``b`` prefixes.
|
||||
|
||||
.. note::
|
||||
|
||||
Python 2's ``u`` prefix is a syntax error in Python 3.2 but it will be
|
||||
allowed again in Python 3.3 thanks to :pep:`414`. Thus, this
|
||||
transformation is optional if you target Python ≥ 3.3. It's still
|
||||
recommended, per the "write Python 3 code" philosophy.
|
||||
|
||||
String handling
|
||||
---------------
|
||||
|
||||
Python 2's `unicode`_ type was renamed :class:`str` in Python 3,
|
||||
``str()`` was renamed :class:`bytes`, and `basestring`_ disappeared.
|
||||
six_ provides :ref:`tools <string-handling-with-six>` to deal with these
|
||||
changes.
|
||||
|
||||
Django also contains several string related classes and functions in the
|
||||
:mod:`django.utils.encoding` and :mod:`django.utils.safestring` modules. Their
|
||||
names used the words ``str``, which doesn't mean the same thing in Python 2
|
||||
and Python 3, and ``unicode``, which doesn't exist in Python 3. In order to
|
||||
avoid ambiguity and confusion these concepts were renamed ``bytes`` and
|
||||
``text``.
|
||||
|
||||
Here are the name changes in :mod:`django.utils.encoding`:
|
||||
|
||||
================== ==================
|
||||
Old name New name
|
||||
================== ==================
|
||||
``smart_str`` ``smart_bytes``
|
||||
``smart_unicode`` ``smart_text``
|
||||
``force_unicode`` ``force_text``
|
||||
================== ==================
|
||||
|
||||
For backwards compatibility, the old names still work on Python 2. Under
|
||||
Python 3, ``smart_str`` is an alias for ``smart_text``.
|
||||
|
||||
For forwards compatibility, the new names work as of Django 1.4.2.
|
||||
|
||||
.. note::
|
||||
|
||||
:mod:`django.utils.encoding` was deeply refactored in Django 1.5 to
|
||||
provide a more consistent API. Check its documentation for more
|
||||
information.
|
||||
|
||||
:mod:`django.utils.safestring` is mostly used via the
|
||||
:func:`~django.utils.safestring.mark_safe` function, which didn't change. In
|
||||
case you're using the internals, here are the name changes:
|
||||
|
||||
================== ==================
|
||||
Old name New name
|
||||
================== ==================
|
||||
``SafeString`` ``SafeBytes``
|
||||
``SafeUnicode`` ``SafeText``
|
||||
================== ==================
|
||||
|
||||
For backwards compatibility, the old names still work on Python 2. On Python 3,
|
||||
``SafeString`` is an alias for ``SafeText``.
|
||||
|
||||
For forwards compatibility, the new names work as of Django 1.4.2.
|
||||
|
||||
``__str__()`` and ``__unicode__()`` methods
|
||||
-------------------------------------------
|
||||
|
||||
In Python 2, the object model specifies :meth:`~object.__str__` and
|
||||
` __unicode__()`_ methods. If these methods exist, they must return
|
||||
``str`` (bytes) and ``unicode`` (text) respectively.
|
||||
|
||||
The ``print`` statement and the :class:`str` built-in call
|
||||
:meth:`~object.__str__` to determine the human-readable representation of an
|
||||
object. The ``unicode`` built-in calls ` __unicode__()`_ if it
|
||||
exists, and otherwise falls back to :meth:`~object.__str__` and decodes the
|
||||
result with the system encoding. Conversely, the
|
||||
:class:`~django.db.models.Model` base class automatically derives
|
||||
:meth:`~object.__str__` from ` __unicode__()`_ by encoding to UTF-8.
|
||||
|
||||
In Python 3, there's simply :meth:`~object.__str__`, which must return ``str``
|
||||
(text).
|
||||
|
||||
(It is also possible to define :meth:`~object.__bytes__`, but Django applications
|
||||
have little use for that method, because they hardly ever deal with ``bytes``.)
|
||||
|
||||
Finally, note that :meth:`~object.__repr__` must return a ``str`` on all
|
||||
versions of Python.
|
||||
|
||||
:class:`dict` and :class:`dict`-like classes
|
||||
--------------------------------------------
|
||||
|
||||
:meth:`dict.keys`, :meth:`dict.items` and :meth:`dict.values` return lists in
|
||||
Python 2 and iterators in Python 3. :class:`~django.http.QueryDict` and the
|
||||
:class:`dict`-like classes defined in ``django.utils.datastructures``
|
||||
behave likewise in Python 3.
|
||||
|
||||
six_ provides compatibility functions to work around this change:
|
||||
:func:`~six.iterkeys`, :func:`~six.iteritems`, and :func:`~six.itervalues`.
|
||||
It also contains an undocumented ``iterlists`` function that works well for
|
||||
``django.utils.datastructures.MultiValueDict`` and its subclasses.
|
||||
|
||||
:class:`~django.http.HttpRequest` and :class:`~django.http.HttpResponse` objects
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
According to :pep:`3333`:
|
||||
|
||||
- headers are always ``str`` objects,
|
||||
- input and output streams are always ``bytes`` objects.
|
||||
|
||||
Specifically, :attr:`HttpResponse.content <django.http.HttpResponse.content>`
|
||||
contains ``bytes``, which may become an issue if you compare it with a
|
||||
``str`` in your tests. The preferred solution is to rely on
|
||||
:meth:`~django.test.SimpleTestCase.assertContains` and
|
||||
:meth:`~django.test.SimpleTestCase.assertNotContains`. These methods accept a
|
||||
response and a unicode string as arguments.
|
||||
|
||||
Coding guidelines
|
||||
=================
|
||||
|
||||
The following guidelines are enforced in Django's source code. They're also
|
||||
recommended for third-party applications that follow the same porting strategy.
|
||||
|
||||
Syntax requirements
|
||||
-------------------
|
||||
|
||||
Unicode
|
||||
~~~~~~~
|
||||
|
||||
In Python 3, all strings are considered Unicode by default. The ``unicode``
|
||||
type from Python 2 is called ``str`` in Python 3, and ``str`` becomes
|
||||
``bytes``.
|
||||
|
||||
You mustn't use the ``u`` prefix before a unicode string literal because it's
|
||||
a syntax error in Python 3.2. You must prefix byte strings with ``b``.
|
||||
|
||||
In order to enable the same behavior in Python 2, every module must import
|
||||
``unicode_literals`` from ``__future__``::
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
my_string = "This is an unicode literal"
|
||||
my_bytestring = b"This is a bytestring"
|
||||
|
||||
If you need a byte string literal under Python 2 and a unicode string literal
|
||||
under Python 3, use the :class:`str` builtin::
|
||||
|
||||
str('my string')
|
||||
|
||||
In Python 3, there aren't any automatic conversions between ``str`` and
|
||||
``bytes``, and the :mod:`codecs` module became more strict. :meth:`str.encode`
|
||||
always returns ``bytes``, and ``bytes.decode`` always returns ``str``. As a
|
||||
consequence, the following pattern is sometimes necessary::
|
||||
|
||||
value = value.encode('ascii', 'ignore').decode('ascii')
|
||||
|
||||
Be cautious if you have to `index bytestrings`_.
|
||||
|
||||
.. _index bytestrings: https://docs.python.org/3/howto/pyporting.html#text-versus-binary-data
|
||||
|
||||
Exceptions
|
||||
~~~~~~~~~~
|
||||
|
||||
When you capture exceptions, use the ``as`` keyword::
|
||||
|
||||
try:
|
||||
...
|
||||
except MyException as exc:
|
||||
...
|
||||
|
||||
This older syntax was removed in Python 3::
|
||||
|
||||
try:
|
||||
...
|
||||
except MyException, exc: # Don't do that!
|
||||
...
|
||||
|
||||
The syntax to reraise an exception with a different traceback also changed.
|
||||
Use :func:`six.reraise`.
|
||||
|
||||
Magic methods
|
||||
-------------
|
||||
|
||||
Use the patterns below to handle magic methods renamed in Python 3.
|
||||
|
||||
Iterators
|
||||
~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
class MyIterator(six.Iterator):
|
||||
def __iter__(self):
|
||||
return self # implement some logic here
|
||||
|
||||
def __next__(self):
|
||||
raise StopIteration # implement some logic here
|
||||
|
||||
Boolean evaluation
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
class MyBoolean(object):
|
||||
|
||||
def __bool__(self):
|
||||
return True # implement some logic here
|
||||
|
||||
def __nonzero__(self): # Python 2 compatibility
|
||||
return type(self).__bool__(self)
|
||||
|
||||
Division
|
||||
~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
class MyDivisible(object):
|
||||
|
||||
def __truediv__(self, other):
|
||||
return self / other # implement some logic here
|
||||
|
||||
def __div__(self, other): # Python 2 compatibility
|
||||
return type(self).__truediv__(self, other)
|
||||
|
||||
def __itruediv__(self, other):
|
||||
return self // other # implement some logic here
|
||||
|
||||
def __idiv__(self, other): # Python 2 compatibility
|
||||
return type(self).__itruediv__(self, other)
|
||||
|
||||
Special methods are looked up on the class and not on the instance to reflect
|
||||
the behavior of the Python interpreter.
|
||||
|
||||
.. module: django.utils.six
|
||||
|
||||
Writing compatible code with six
|
||||
--------------------------------
|
||||
|
||||
six_ is the canonical compatibility library for supporting Python 2 and 3 in
|
||||
a single codebase. Read its documentation!
|
||||
|
||||
A :mod:`customized version of six <django.utils.six>` is bundled with Django
|
||||
as of version 1.4.2. You can import it as ``django.utils.six``.
|
||||
|
||||
Here are the most common changes required to write compatible code.
|
||||
|
||||
.. _string-handling-with-six:
|
||||
|
||||
String handling
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The ``basestring`` and ``unicode`` types were removed in Python 3, and the
|
||||
meaning of ``str`` changed. To test these types, use the following idioms::
|
||||
|
||||
isinstance(myvalue, six.string_types) # replacement for basestring
|
||||
isinstance(myvalue, six.text_type) # replacement for unicode
|
||||
isinstance(myvalue, bytes) # replacement for str
|
||||
|
||||
Python ≥ 2.6 provides ``bytes`` as an alias for ``str``, so you don't need
|
||||
:data:`six.binary_type`.
|
||||
|
||||
``long``
|
||||
~~~~~~~~
|
||||
|
||||
The ``long`` type no longer exists in Python 3. ``1L`` is a syntax error. Use
|
||||
:data:`six.integer_types` check if a value is an integer or a long::
|
||||
|
||||
isinstance(myvalue, six.integer_types) # replacement for (int, long)
|
||||
|
||||
``xrange``
|
||||
~~~~~~~~~~
|
||||
|
||||
If you use ``xrange`` on Python 2, import ``six.moves.range`` and use that
|
||||
instead. You can also import ``six.moves.xrange`` (it's equivalent to
|
||||
``six.moves.range``) but the first technique allows you to simply drop the
|
||||
import when dropping support for Python 2.
|
||||
|
||||
Moved modules
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Some modules were renamed in Python 3. The ``django.utils.six.moves``
|
||||
module (based on the :mod:`six.moves module <six.moves>`) provides a
|
||||
compatible location to import them.
|
||||
|
||||
``PY2``
|
||||
~~~~~~~
|
||||
|
||||
If you need different code in Python 2 and Python 3, check :data:`six.PY2`::
|
||||
|
||||
if six.PY2:
|
||||
# compatibility code for Python 2
|
||||
|
||||
This is a last resort solution when :mod:`six` doesn't provide an appropriate
|
||||
function.
|
||||
|
||||
.. module:: django.utils.six
|
||||
|
||||
Django customized version of ``six``
|
||||
------------------------------------
|
||||
|
||||
The version of six bundled with Django (``django.utils.six``) includes a few
|
||||
customizations for internal use only.
|
||||
|
||||
.. _unicode: https://docs.python.org/2/library/functions.html#unicode
|
||||
.. _ __unicode__(): https://docs.python.org/2/reference/datamodel.html#object.__unicode__
|
||||
.. _basestring: https://docs.python.org/2/library/functions.html#basestring
|
|
@ -177,9 +177,9 @@ control the particular collation used by the test database. See the
|
|||
:doc:`settings documentation </ref/settings>` for details of these
|
||||
and other advanced settings.
|
||||
|
||||
If using an SQLite in-memory database with Python 3.4+ and SQLite 3.7.13+,
|
||||
`shared cache <https://www.sqlite.org/sharedcache.html>`_ will be enabled, so
|
||||
you can write tests with ability to share the database between threads.
|
||||
If using an SQLite in-memory database with SQLite 3.7.13+, `shared cache
|
||||
<https://www.sqlite.org/sharedcache.html>`_ is enabled, so you can write tests
|
||||
with ability to share the database between threads.
|
||||
|
||||
.. admonition:: Finding data from your production database when running tests?
|
||||
|
||||
|
|
|
@ -1708,9 +1708,9 @@ Management commands can be tested with the
|
|||
:func:`~django.core.management.call_command` function. The output can be
|
||||
redirected into a ``StringIO`` instance::
|
||||
|
||||
from io import StringIO
|
||||
from django.core.management import call_command
|
||||
from django.test import TestCase
|
||||
from django.utils.six import StringIO
|
||||
|
||||
class ClosepollTest(TestCase):
|
||||
def test_command_output(self):
|
||||
|
|
Loading…
Reference in New Issue