views:

59

answers:

1

This is my class:

class Account(models.Model):

    name = models.CharField(max_length=255)

    def __unicode__(self):
        return '{0}'.format(self.name)

class Painting(models.Model):

    account = models.ForeignKey(Account)
    color = models.CharField(max_length=255)

    def __unicode__(self):
        return 'Account: {0} - Color: {1}'.format(self.account, self.color)

This is my shell:

>>> from somewhere import Account, Painting
>>> acct = Account(name='Acme')
>>> acct.save()
>>> ptng = Painting(account=acct, color='FF0000')
>>> ptng.save()
>>> print(ptng)
FF0000
>>> 
>>> # Make another instance for next demonstration:
>>> 
>>> ptng_2 = Painting(account=acct, color='CC0000')
>>> ptng_2.save()
>>> 
>>> # Check for 'FF0000' in all the objects:
>>> 
>>> allptngs = Painting.objects.filter(account=acct)
>>> 'FF0000' in allptngs
False
>>> for p in allptngs:
>>>     print(p)
...
...
FF0000
CC0000
>>> 
>>> # Now with unicode():
>>> 
>>> for p in allptngs:
>>>     unicode(p)
...
...
u'FF0000'
u'CC0000'

Notice how when printed the Painting object doesn't output via the __unicode__ method, but rather prints the color attribute. Why is this?

Then notice that when I ask if 'FF0000' is in allptngs, it returns false, but if I loop through allptngs and print each, 'FF0000' is indeed in the iterable. This is very confusing.

Update: I forgot to mention unicode(object) returns the same thing as print(object) in my example above.

+3  A: 

Notice how when printed the Painting object doesn't output via the unicode method, but rather prints the color attribute. Why is this?

print(x) calls x.__str__(), not x.__unicode__(). Django makes an effort to use unicode strings to represent things, and hence in many important places where it needs to render a textual representation of the object, it will use the x.__unicode__() by default. But you are using a builtin python command, and that command always calls x.__str__().

Then notice that when I ask if 'FF0000' is in allptngs, it returns false, but if I loop through allptngs and print each, 'FF0000' is indeed in the iterable. This is very confusing.

This is entirely consistent. a in b verifies whether a is equal to any element in b. This is not the same as a being equal to the string representation of some element of b.

My recommendation is to add to your model:

def __str__(self):
    return self.__unicode__()
David Berger