tomtom92 tomtom92 - 4 months ago 12
Python Question

'NoneType' object has no attribute, reference class variable declared before __init__

I am using Flask with SQLAlchemy to create a 1-to-1 relationship between a Search request and parsed Data. Once a user has checked over the search results, they can click continue to parse the data (and create a Data class instance). However, I am unsure how to reference class variables before an

__init__
reference. I want my
Data
instance to have a requests response object
r
.

Calling code (views.py):

search = Search(form) # create source result
search.author = g.user
db.session.add(search)
db.session.commit()

...

data = Data()
data.search_id = this_search.id
db.session.add(data)
db.session.commit()


Search class (models.py):

class Search(db.Model):
id = db.Column(db.Integer, primary_key=True)
timestamp = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

data_id = db.relationship('Data', backref='source', lazy='dynamic')
...


Data class (models.py):

class Data(db.Model):
id = db.Column(db.Integer, primary_key=True)
search_id = db.Column(db.Integer, db.ForeignKey('search.id'))
search = db.relationship('Search', backref="information")
r = None

def __init__(self):
self.r = requests.get(self.search.url)


The error I get is:


AttributeError: 'NoneType' object has no attribute 'url'


It is clear that I cannot create
self.r
before the
Data.search
variable is declared, since the error suggests that it is
NoneType
type. I am not sure what the proper format creating new variables like this should be. The code works if I move the
self.r
declaration to a class method that is called after initialization. Thanks!

Answer

A few recommendations

The search attributes actually is declared, it's just not set. If it wasn't declared, you would get an AttributeError.

Call the superclass __init__. This is just good practice for all classes

def __init__(*args, **kwargs):
    super(Data, self).__init__(*args, **kwargs)

You could compute the value lazily

class Data(...):
    ...
    def __init__(...):
        ...
        self._r = None

    @property
    def r(self):
        if self._r is None and self.search is not None:
            self._r = requests.get(self.search.url)
        return self._r