From a9dd6221af2148410c8a26dcbafd1ff8cc0fb107 Mon Sep 17 00:00:00 2001
From: Claude Paroz <claude@2xlibre.net>
Date: Thu, 4 Jul 2013 15:19:33 +0200
Subject: [PATCH] [1.6.x] Fixed #20224 -- Update docs examples which mention
 __unicode__

Thanks Marc Tamlyn and Tim Graham for the review.
Backport of 7442eb1a24 from master.
---
 django/contrib/gis/management/commands/ogrinspect.py |  2 +-
 django/contrib/gis/utils/ogrinspect.py               |  5 +++--
 docs/howto/custom-model-fields.txt                   |  6 +++---
 .../contributing/writing-code/coding-style.txt       |  5 ++++-
 docs/intro/overview.txt                              |  2 ++
 docs/ref/contrib/admin/actions.txt                   |  1 +
 docs/ref/contrib/admin/index.txt                     |  5 +++--
 docs/ref/contrib/contenttypes.txt                    |  1 +
 docs/ref/contrib/gis/commands.txt                    |  4 ++--
 docs/ref/contrib/gis/layermapping.txt                |  2 ++
 docs/ref/contrib/gis/tutorial.txt                    |  1 +
 docs/ref/forms/api.txt                               |  3 ++-
 docs/ref/forms/fields.txt                            | 12 ++++++------
 docs/ref/models/instances.txt                        |  6 ++++++
 docs/ref/models/querysets.txt                        |  1 +
 docs/ref/utils.txt                                   |  6 ++++--
 docs/topics/auth/customizing.txt                     |  1 +
 docs/topics/class-based-views/generic-display.txt    |  2 ++
 docs/topics/db/examples/many_to_many.txt             |  2 ++
 docs/topics/db/examples/many_to_one.txt              |  8 +++++---
 docs/topics/db/examples/one_to_one.txt               |  3 +++
 docs/topics/db/models.txt                            |  7 ++++++-
 docs/topics/db/queries.txt                           |  3 +++
 docs/topics/forms/modelforms.txt                     |  1 +
 24 files changed, 65 insertions(+), 24 deletions(-)

diff --git a/django/contrib/gis/management/commands/ogrinspect.py b/django/contrib/gis/management/commands/ogrinspect.py
index 44513e3463..2a29fe672a 100644
--- a/django/contrib/gis/management/commands/ogrinspect.py
+++ b/django/contrib/gis/management/commands/ogrinspect.py
@@ -53,7 +53,7 @@ class Command(LabelCommand):
         make_option('--multi-geom', action='store_true', dest='multi_geom', default=False,
                     help='Treat the geometry in the data source as a geometry collection.'),
         make_option('--name-field', dest='name_field',
-                    help='Specifies a field name to return for the `__unicode__` function.'),
+                    help='Specifies a field name to return for the `__unicode__`/`__str__` function.'),
         make_option('--no-imports', action='store_false', dest='imports', default=True,
                     help='Do not include `from django.contrib.gis.db import models` '
                     'statement.'),
diff --git a/django/contrib/gis/utils/ogrinspect.py b/django/contrib/gis/utils/ogrinspect.py
index 08d3b40397..b7cfafd49d 100644
--- a/django/contrib/gis/utils/ogrinspect.py
+++ b/django/contrib/gis/utils/ogrinspect.py
@@ -89,7 +89,7 @@ def ogrinspect(*args, **kwargs):
      `multi_geom` => Boolean (default: False) - specify as multigeometry.
 
      `name_field` => String - specifies a field name to return for the
-       `__unicode__` function (which will be generated if specified).
+       `__unicode__`/`__str__` function (which will be generated if specified).
 
      `imports` => Boolean (default: True) - set to False to omit the
        `from django.contrib.gis.db import models` code from the
@@ -221,4 +221,5 @@ def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non
 
     if name_field:
         yield ''
-        yield '    def __str__(self): return self.%s' % name_field
+        yield '    def __%s__(self): return self.%s' % (
+            'str' if six.PY3 else 'unicode', name_field)
diff --git a/docs/howto/custom-model-fields.txt b/docs/howto/custom-model-fields.txt
index 85c71004f4..5a5bef9141 100644
--- a/docs/howto/custom-model-fields.txt
+++ b/docs/howto/custom-model-fields.txt
@@ -710,9 +710,9 @@ smoothly:
    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 ``__unicode__()`` method automatically
-   converts to the string form of your Python object, you can save yourself
-   a lot of work.
+   ``HandField``). So if your ``__unicode__()`` method (``__str__()`` on
+   Python 3) automatically converts to the string form of your Python object,
+   you can save yourself a lot of work.
 
 
 Writing a ``FileField`` subclass
diff --git a/docs/internals/contributing/writing-code/coding-style.txt b/docs/internals/contributing/writing-code/coding-style.txt
index 21146600b4..437d2f7ec5 100644
--- a/docs/internals/contributing/writing-code/coding-style.txt
+++ b/docs/internals/contributing/writing-code/coding-style.txt
@@ -124,13 +124,16 @@ Model style
           first_name = models.CharField(max_length=20)
           last_name = models.CharField(max_length=40)
 
+* If you define a ``__str__`` method (previously ``__unicode__`` before Python 3
+  was supported), decorate the model class with
+  :func:`~django.utils.encoding.python_2_unicode_compatible`.
+
 * The order of model inner classes and standard methods should be as
   follows (noting that these are not all required):
 
   * All database fields
   * Custom manager attributes
   * ``class Meta``
-  * ``def __unicode__()``
   * ``def __str__()``
   * ``def save()``
   * ``def get_absolute_url()``
diff --git a/docs/intro/overview.txt b/docs/intro/overview.txt
index 77838ffcaa..55366fb2c6 100644
--- a/docs/intro/overview.txt
+++ b/docs/intro/overview.txt
@@ -31,6 +31,7 @@ the file ``mysite/news/models.py``::
     class Reporter(models.Model):
         full_name = models.CharField(max_length=70)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.full_name
 
@@ -40,6 +41,7 @@ the file ``mysite/news/models.py``::
         content = models.TextField()
         reporter = models.ForeignKey(Reporter)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.headline
 
diff --git a/docs/ref/contrib/admin/actions.txt b/docs/ref/contrib/admin/actions.txt
index c79f978850..65d096921f 100644
--- a/docs/ref/contrib/admin/actions.txt
+++ b/docs/ref/contrib/admin/actions.txt
@@ -57,6 +57,7 @@ simple news application with an ``Article`` model::
         body = models.TextField()
         status = models.CharField(max_length=1, choices=STATUS_CHOICES)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.title
 
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index 318ce297a2..70db52941c 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -438,7 +438,8 @@ 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 ``__unicode__()`` representation of each object.
+    column that displays the ``__unicode__()`` (``__str__()`` on Python 3)
+    representation of each object.
 
     You have four possible values that can be used in ``list_display``:
 
@@ -488,7 +489,7 @@ subclass::
     A few special cases to note about ``list_display``:
 
     * If the field is a ``ForeignKey``, Django will display the
-      ``__unicode__()`` of the related object.
+      ``__unicode__()`` (``__str__()`` on Python 3) of the related object.
 
     * ``ManyToManyField`` fields aren't supported, because that would
       entail executing a separate SQL statement for each row in the table.
diff --git a/docs/ref/contrib/contenttypes.txt b/docs/ref/contrib/contenttypes.txt
index 199401c64a..fcd66a5b03 100644
--- a/docs/ref/contrib/contenttypes.txt
+++ b/docs/ref/contrib/contenttypes.txt
@@ -270,6 +270,7 @@ A simple example is a tagging system, which might look like this::
         object_id = models.PositiveIntegerField()
         content_object = generic.GenericForeignKey('content_type', 'object_id')
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.tag
 
diff --git a/docs/ref/contrib/gis/commands.txt b/docs/ref/contrib/gis/commands.txt
index 015a1f9741..3bacb03bc1 100644
--- a/docs/ref/contrib/gis/commands.txt
+++ b/docs/ref/contrib/gis/commands.txt
@@ -65,8 +65,8 @@ of using ``ogrinspect`` :ref:`in the tutorial <ogrinspect-intro>`.
 
 .. django-admin-option:: --name-field <name_field>
 
-   Generates a ``__unicode__`` routine on the model that will return the
-   the given field name.
+   Generates a ``__unicode__`` routine (``__str__`` on Python 3) on the model
+   that will return the the given field name.
 
 .. django-admin-option:: --no-imports
 
diff --git a/docs/ref/contrib/gis/layermapping.txt b/docs/ref/contrib/gis/layermapping.txt
index dd0a41cbc0..381c7df133 100644
--- a/docs/ref/contrib/gis/layermapping.txt
+++ b/docs/ref/contrib/gis/layermapping.txt
@@ -60,6 +60,8 @@ 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
         objects = models.GeoManager()
+
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return 'Name: %s' % self.name
 
diff --git a/docs/ref/contrib/gis/tutorial.txt b/docs/ref/contrib/gis/tutorial.txt
index 56d90c8593..3df4db12a0 100644
--- a/docs/ref/contrib/gis/tutorial.txt
+++ b/docs/ref/contrib/gis/tutorial.txt
@@ -244,6 +244,7 @@ model to represent this data::
         objects = models.GeoManager()
 
         # Returns the string representation of the model.
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.name
 
diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt
index aa19719a68..5d54e01c3d 100644
--- a/docs/ref/forms/api.txt
+++ b/docs/ref/forms/api.txt
@@ -566,7 +566,8 @@ Customizing the error list format
 
 By default, forms use ``django.forms.util.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::
+pass that in at construction time (replace ``__unicode__`` by ``__str__`` on
+Python 3)::
 
     >>> from django.forms.util import ErrorList
     >>> class DivErrorList(ErrorList):
diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
index 69e3aa71ad..ef4ed729bd 100644
--- a/docs/ref/forms/fields.txt
+++ b/docs/ref/forms/fields.txt
@@ -1000,12 +1000,12 @@ objects (in the case of ``ModelMultipleChoiceField``) into the
         initial value, no empty choice is created (regardless of the value
         of ``empty_label``).
 
-    The ``__unicode__`` 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 ``__unicode__`` (``__str__`` on Python 3) 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
 
diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt
index 17c9aa9fb7..f06866d9a1 100644
--- a/docs/ref/models/instances.txt
+++ b/docs/ref/models/instances.txt
@@ -430,6 +430,12 @@ Other model instance methods
 
 A few object methods have special purposes.
 
+.. note::
+    On Python 3, as all strings are natively considered Unicode, only use the
+    ``__str__()`` method (the ``__unicode__()`` method is obsolete).
+    If you'd like compatibility with Python 2, you can decorate your model class
+    with :func:`~django.utils.encoding.python_2_unicode_compatible`.
+
 ``__unicode__``
 ---------------
 
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index 2db252d006..f9d5d001f8 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -830,6 +830,7 @@ For example, suppose you have these models::
         name = models.CharField(max_length=50)
         toppings = models.ManyToManyField(Topping)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return u"%s (%s)" % (self.name, u", ".join([topping.name
                                                         for topping in self.toppings.all()]))
diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
index 8d722829fb..15f65c121f 100644
--- a/docs/ref/utils.txt
+++ b/docs/ref/utils.txt
@@ -471,12 +471,14 @@ Atom1Feed
         def fancy_utility_function(s, ...):
             # Do some conversion on string 's'
             ...
+        # Replace unicode by str on Python 3
         fancy_utility_function = allow_lazy(fancy_utility_function, unicode)
 
     The ``allow_lazy()`` decorator takes, in addition to the function to decorate,
     a number of extra arguments (``*args``) specifying the type(s) that the
-    original function can return. Usually, it's enough to include ``unicode`` here
-    and ensure that your function returns only Unicode strings.
+    original function can return. Usually, it's enough to include ``unicode``
+    (or ``str`` on Python 3) here and ensure that your function returns only
+    Unicode strings.
 
     Using this decorator means you can write your function and assume that the
     input is a proper string, then add support for lazy translation objects at the
diff --git a/docs/topics/auth/customizing.txt b/docs/topics/auth/customizing.txt
index eb2fff05f5..18c30122fc 100644
--- a/docs/topics/auth/customizing.txt
+++ b/docs/topics/auth/customizing.txt
@@ -1002,6 +1002,7 @@ authentication app::
             # The user is identified by their email address
             return self.email
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.email
 
diff --git a/docs/topics/class-based-views/generic-display.txt b/docs/topics/class-based-views/generic-display.txt
index 8c2d0db041..2f8d561541 100644
--- a/docs/topics/class-based-views/generic-display.txt
+++ b/docs/topics/class-based-views/generic-display.txt
@@ -89,6 +89,7 @@ We'll be using these models::
         class Meta:
             ordering = ["-name"]
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.name
 
@@ -98,6 +99,7 @@ We'll be using these models::
         email = models.EmailField()
         headshot = models.ImageField(upload_to='author_headshots')
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.name
 
diff --git a/docs/topics/db/examples/many_to_many.txt b/docs/topics/db/examples/many_to_many.txt
index 2076427768..42fa9cc1a1 100644
--- a/docs/topics/db/examples/many_to_many.txt
+++ b/docs/topics/db/examples/many_to_many.txt
@@ -16,6 +16,7 @@ objects, and a ``Publication`` has multiple ``Article`` objects:
     class Publication(models.Model):
         title = models.CharField(max_length=30)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.title
 
@@ -26,6 +27,7 @@ objects, and a ``Publication`` has multiple ``Article`` objects:
         headline = models.CharField(max_length=100)
         publications = models.ManyToManyField(Publication)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.headline
 
diff --git a/docs/topics/db/examples/many_to_one.txt b/docs/topics/db/examples/many_to_one.txt
index c869362d16..af112144b3 100644
--- a/docs/topics/db/examples/many_to_one.txt
+++ b/docs/topics/db/examples/many_to_one.txt
@@ -15,6 +15,7 @@ To define a many-to-one relationship, use :class:`~django.db.models.ForeignKey`.
         last_name = models.CharField(max_length=30)
         email = models.EmailField()
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return u"%s %s" % (self.first_name, self.last_name)
 
@@ -23,6 +24,7 @@ To define a many-to-one relationship, use :class:`~django.db.models.ForeignKey`.
         pub_date = models.DateField()
         reporter = models.ForeignKey(Reporter)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.headline
 
@@ -56,9 +58,9 @@ Article objects have access to their related Reporter objects::
 
     >>> r = a.reporter
 
-These are strings 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)::
+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')
diff --git a/docs/topics/db/examples/one_to_one.txt b/docs/topics/db/examples/one_to_one.txt
index 09634c84c7..a86e5ed0ac 100644
--- a/docs/topics/db/examples/one_to_one.txt
+++ b/docs/topics/db/examples/one_to_one.txt
@@ -16,6 +16,7 @@ In this example, a ``Place`` optionally can be a ``Restaurant``:
         name = models.CharField(max_length=50)
         address = models.CharField(max_length=80)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return u"%s the place" % self.name
 
@@ -24,6 +25,7 @@ In this example, a ``Place`` optionally can be a ``Restaurant``:
         serves_hot_dogs = models.BooleanField()
         serves_pizza = models.BooleanField()
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return u"%s the restaurant" % self.place.name
 
@@ -31,6 +33,7 @@ In this example, a ``Place`` optionally can be a ``Restaurant``:
         restaurant = models.ForeignKey(Restaurant)
         name = models.CharField(max_length=50)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return u"%s the waiter at %s" % (self.name, self.restaurant)
 
diff --git a/docs/topics/db/models.txt b/docs/topics/db/models.txt
index c0ba53ddd7..2b565758e7 100644
--- a/docs/topics/db/models.txt
+++ b/docs/topics/db/models.txt
@@ -416,6 +416,7 @@ something like this::
     class Person(models.Model):
         name = models.CharField(max_length=128)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.name
 
@@ -423,6 +424,7 @@ something like this::
         name = models.CharField(max_length=128)
         members = models.ManyToManyField(Person, through='Membership')
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.name
 
@@ -709,7 +711,10 @@ 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.__unicode__`
+:meth:`~Model.__str__` (Python 3)
+    Python 3 equivalent of ``__unicode__()``.
+
+:meth:`~Model.__unicode__` (Python 2)
     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
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
index bdbdd3fa2a..4aa9429c73 100644
--- a/docs/topics/db/queries.txt
+++ b/docs/topics/db/queries.txt
@@ -23,6 +23,7 @@ models, which comprise a Weblog application:
         name = models.CharField(max_length=100)
         tagline = models.TextField()
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.name
 
@@ -30,6 +31,7 @@ models, which comprise a Weblog application:
         name = models.CharField(max_length=50)
         email = models.EmailField()
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.name
 
@@ -44,6 +46,7 @@ models, which comprise a Weblog application:
         n_pingbacks = models.IntegerField()
         rating = models.IntegerField()
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.headline
 
diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt
index bd9e14aea4..d961ee41d5 100644
--- a/docs/topics/forms/modelforms.txt
+++ b/docs/topics/forms/modelforms.txt
@@ -162,6 +162,7 @@ Consider this set of models::
         title = models.CharField(max_length=3, choices=TITLE_CHOICES)
         birth_date = models.DateField(blank=True, null=True)
 
+        # On Python 3: def __str__(self):
         def __unicode__(self):
             return self.name