Opened 11 years ago

Closed 11 years ago

Last modified 10 years ago

#19928 closed Uncategorized (invalid)

python_2_unicode_compatible breaks Python 2

Reported by: Vernon Cole Owned by: nobody
Component: Uncategorized Version: dev
Severity: Normal Keywords: porting to python 3
Cc: m.r.sopacua@… Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Following the example in https://docs.djangoproject.com/en/1.5/topics/python3/
I made my models.py look like this:

from __future__ import unicode_literals
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
#@python_2_unicode_compatible
class Ward_Name(models.Model):
    state = models.CharField("State", max_length=55,
        help_text="Nigearin State (large political subdivision)")
    lga = models.CharField("LGA", max_length=255, blank=True,
        help_text="Nigerain Local Government Area (medium political subdivision)")
    ward = models.CharField(max_length=255, blank=True,
        help_text="Ward (small political subdivision)")
    db_ward = models.CharField("Db Ward",max_length=255, blank=True,
        help_text="database altered version of Ward name")
    def __str__(self):
        return str('State={}, LGA={}, Ward={}, called "{}"'.format(
            self.state, self.lga, self.ward, self.db_ward))
    class Meta:
        unique_together = (("lga","ward"))
        index_together = [["lga","ward"]]

Note that the decorator is commented out...
I test using the following code, which works in both Python2.7 and Python3.3
$python manage.py x_test

from __future__ import print_function
from django.core.management.base import BaseCommand
from nomads.models import Ward_Name

class Command(BaseCommand):
    args = "<(none)>"
    help = 'test reading Ward Name data table'

    def handle(self, *args, **options):
        self.test_read(*args)

    def test_read(self, *args):
        qs = Ward_Name.objects.all()
        for w in qs:
            print('Ward=',w)

When I un-comment the decorator the program fails under python 2

$ python manage.py x_test
RuntimeError: maximum recursion depth exceeded while calling a Python object

Is the error in the django 1.5 code, the documentation, or my understanding?

(the work-around is easy: just do not use the feature and everything works in both versions)

(My environment is: Ubuntu 12.10 64 bit
django 1.5stable pulled from github this morning

Change History (3)

comment:1 by Aymeric Augustin, 11 years ago

Resolution: invalid
Status: newclosed

The docs say "you must define a __str__() method returning text".

Your __str__() method returns a bytestring under Python 2.

comment:2 by Melvyn Sopacua, 10 years ago

Cc: m.r.sopacua@… added

I'd like to reopen this issue or create a new one for expanding the documentation. It's very slim on the whole str method in python 2 and specifically doesn't deal with abstract classes. I just spent quite a bit of time debugging this issue, where I had the str() method defined in the abstract class and repeated the decorator on derived classes. I'm guessing this is the error and somehow things get screwed when doing it like that. No matter what I returned in the abstract class I got the recursion error. When I finally reimplemented the method in the derived class and gave back a simple string literal, things went ok.
I'm still figuring out how to deal with it, cause what I really want to return is a property of a foreign key.
Anyway, reopen this, or create a new one?

comment:3 by Aymeric Augustin, 10 years ago

Don't repeat the decorator on derived classes. It's only appropriate on the class that defines __str__.

Note: See TracTickets for help on using tickets.
Back to Top