views:

99

answers:

3

How can I test to see if a class contains a particular attribute?

In [14]: user = User.objects.get(pk=2)  

In [18]: user.__dict__  
Out[18]:   
{'date_joined': datetime.datetime(2010, 3, 17, 15, 20, 45),  
 'email': u'[email protected]',  
 'first_name': u'',  
 'id': 2L,  
 'is_active': 1,  
 'is_staff': 0,  
 'is_superuser': 0,  
 'last_login': datetime.datetime(2010, 3, 17, 16, 15, 35),  
 'last_name': u'',  
 'password': u'sha1$44a2055f5',  
 'username': u'DickCheney'}  

In [25]: hasattr(user, 'username')  
Out[25]: True  

In [26]: hasattr(User, 'username')  
Out[26]: False  

I'm having a weird bug where more attributes are showing up than I actually define. I want to conditionally stop this.

e.g.

if not hasattr(User, 'karma'):
  User.add_to_class('karma', models.PositiveIntegerField(default=1)) 
+3  A: 

Hey Bryan,

as far as I know there is no method like hasattr() for Django models. But there is a way to check if a Django model has a certain field.

To test this I would recommend you to access the Django (Python) shell:

$> python manage.py shell

Now import the User model:

$> from django.contrib.auth.models import User

Get the meta information of the model:

$> opts = User._meta

To check a field use the following command:

$> opts.get_field('username')

In case of the User model there will be printed out a message like this:

<django.db.models.fields.CharField object at 0x1024750>

If the field you are looking for is not part of the model a FieldDoesNotExist will be thrown. With this knowledge you should be able to check the existence of a field programmatically.

You can read more about that here: b-list.org: Working with models

Jens
+1  A: 

I agree with the comments made in the question about EAFP, but conversely there are some scenarios when you need to LBYL (Look Before You Leap).

An approach for Python classes in general won't work for Django models, as Django's metaclass magic means that fields are not contained in the model class' __dict__. So, specifically for Django models, you can do something like the following function:

def django_model_has_field(model_class, field_name):
    return field_name in model_class._meta.get_all_field_names()
Vinay Sajip
+1  A: 

The User class doesn't have a username attribute, because model fields are added by the metaclass at initialization time. But you can check that a model defines a particular field by using Model._meta.get_field(filename).

Daniel Roseman