views:

1235

answers:

4

I have a model Product

it has two fields size & colours among others

colours = models.CharField(blank=True, null=True, max_length=500)
size = models.CharField(blank=True, null=True, max_length=500)

In my view I have

current_product = Product.objects.get(slug=title)
if len(current_product.size) != 0 :
    current_product.size = current_product.size.split(",")

and get this error:

object of type 'NoneType' has no len()

What is NoneType and how can I test for it?

+4  A: 

NoneType is the type that the None value has. You want to change the second snippet to

if current_product.size: # This will evaluate as false if size is None or len(size) == 0.
  blah blah
ruds
Cheers,I thought I'd tried that. That's why I was trying testing the length. Ah well. You get this on the big jobs
Cato Johnston
You do at that. I like this idiom -- it eliminates an "or" that makes the code less readable, and that's easy to forget (as illustrated here :) )
ruds
Please use "is not None" rather than assuming that None is like False -- it make the if statement perfectly clear.
S.Lott
@S.Lott: I don't see any reason to test for None specifically in this case. The purpose is to test whether current_product.size has any contents, and this does that more clearly than a complicated double-check for "is not None" and len().
Carl Meyer
@Carl Meyer: Exactly. "is not None" is the correct idiom when you're testing for None-ness, but if you're checking whether a list is both non-None *and* has contents, use the list as a boolean value.
ruds
A: 

NoneType is Pythons NULL-Type, meaning "nothing", "undefined". It has only one value: "None". When creating a new model object, its attributes are usually initialized to None, you can check that by comparing:

if someobject.someattr is None:
    # Not set yet
Ferdinand Beyer
Calling it "undefined" is a bit facetious. The variable/name is defined, but it has no useful value.
Ignacio Vazquez-Abrams
A: 

I don't know Django, but I assume that some kind of ORM is involved when you do this:

current_product = Product.objects.get(slug=title)

At that point you should always check whether you get None back ('None' is the same as 'null' in Java or 'nil' in Lisp with the subtle difference that 'None' is an object in Python). This is usually the way ORMs map the empty set to the programming language.

EDIT: Gee, I just see that it's current_product.size that's None not current_product. As said, I'm not familiar with Django's ORM, but this seems strange nevertheless: I'd either expect current_product to be None or size having a numerical value.

paprika
In fact, Django will raise an exception in this case (Product.NotFound).
Ferdinand Beyer
A: 

I can best explain the NoneType error with this example of erroneous code:

def test():  
    s = list([1,'',2,3,4,'',5])  
    try:  
        s = s.remove('') # <-- THIS WRONG because it turns s in to a NoneType  
    except:  
        pass  
    print(str(s))  

# s.remove() returns nothing also known as NoneType. The correct way  
def test2()  
    s = list([1,'',2,3,4,'',5])  
    try:  
        s.remove('') # <-- CORRECTED  
    except:  
        pass  
    print(str(s))
baudsmoke