Krystian Cybulski
Krystian Cybulski

Reputation: 11118

A model with a defined field throws an AttributeError when accessing it

I have a Django 1.5 app with a custom User model. It has the following field (among a bunch of others):

class User(models.Model):
    ...

    reporting_period = models.CharField(
        max_length=20,
        choices=REPORTING_PERIODS,
        null=True,
        blank=True,
        default=None
    )

    company = models.ForeignKey(
        Company,
        null=True,
        blank=True,
        default=None
    )

This model also has the following function defined:

def get_reporting_period(self, company_reporting_period=None):
    if not self.reporting_period:
        if not hasattr(self, '_company_reporting_period'):
            if company_reporting_period:
                self._company_reporting_period = company_reporting_period
            else:
                self._company_reporting_period = self.company.reporting_period
        return self._company_reporting_period
    else:
        return self.reporting_period

Occasionally, the get_reporting_period function throws an AttributeError ('User' object has no attribute 'reporting_period') on the line if not self.reporting_period:. I am scratching my head as to how that is possible.

self is a User instance, and therefore should have a reporting_period at all times. Are there any times during a model instance's lifetime in Django when a field is not accessible as a property?

Unfortunately, the issue only happens in my production environment where I am unable to debug it.

Upvotes: 0

Views: 58

Answers (1)

knbk
knbk

Reputation: 53699

Field attributes on instances are not defined until the __init__ method of the Model class is called. Trying to access a field attribute in a custom __init__ method before calling the super method will result in an AttributeError.

Otherwise something must've accidentally deleted the attribute on the instance.

I believe that are the only two instances when a field attribute is not defined on a model instance.

EDIT: I've done a small test, and unpickling preserves the attributes of the original version of the model, but new methods carry over to the recreated model. So you would be able to call the new get_reporting_period function, but it would raise an AttributeError when trying to access the undefined reporting_period attribute.

That means that in this case you should invalidate your cached entries after adding a new field. However, there are plenty of serialization methods that would not result in such an error. Take a look at the answer to this question for a way to serialize models without this problem.

Upvotes: 1

Related Questions