1
0
mirror of https://github.com/django/django.git synced 2024-12-22 09:05:43 +00:00

Refs #23919 -- Removed Python 2 notes in docs.

This commit is contained in:
Tim Graham 2017-01-18 11:51:29 -05:00 committed by GitHub
parent c716fe8782
commit f6acd1d271
61 changed files with 139 additions and 731 deletions

View File

@ -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),
}

View File

@ -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.

View File

@ -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>`

View File

@ -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`.

View File

@ -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
================================

View File

@ -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

View File

@ -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):

View File

@ -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
====================

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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',
],

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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``.

View File

@ -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::

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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::

View File

@ -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

View File

@ -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()),

View File

@ -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()

View File

@ -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.

View File

@ -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'

View File

@ -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 '/'

View File

@ -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)

View File

@ -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()``

View File

@ -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

View File

@ -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.

View File

@ -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).

View File

@ -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.

View File

@ -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).

View File

@ -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).

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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).

View File

@ -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):

View File

@ -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:

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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::

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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?

View File

@ -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):