Search code examples
pythonexceptionflaskclass-methodattributeerror

Python class method throws AttributeError


I'm having issues getting a class method to run in Flask.

In models/User.py:

from mongoengine import *

class User(Document):
  first_name = StringField()
  last_name = StringField()
  ...

  def __init__(self, arg1, arg2, ...):
    self.first_name = arg1
    self.last_name = arg2
    ...

  @classmethod
  def create(self, arg1, arg2, ...):
    #do some things like salting and hashing passwords...
    user = self(arg1, arg2, ...)
    user.save()
    return user

In the main application python file:

from models import User
...
def func():
  ...

  #Throws "AttributeError: type object 'User' has no attribute 'create'"
  user = User.create(arg1, arg2, ...) 

Shouldn't I be able to call create on the User class without instantiating a User object? I'm using Python 2.7.2, and I also tried the non-decorator syntax of using create = classmethod(create), but that didn't work. Thanks in advance!

EDIT: I found one issue: that the models folder did not contain an __init__.py file, so it wasn't a module, so from models import User was not actually importing the file I wanted it to. It did not give me an error from before because I used to have a models.py module in the same directory as the application python script, but after deleting it I never deleted the corresponding .pyc file. Now, I'm getting the error AttributeError: 'module' object has no attribute 'create' instead of what I had before, but I'm certain it is importing the correct file now.

EDIT2: Solved. I then changed the import to from models.User import User and It's hitting the method now.


Solution

  • The issue was twofold:

    1. The User.py file was in the models/ folder, meaning that my import was actually looking for the User class in the models.py file, which no longer existed but still was being imported without error because the models.pyc file was still around
    2. The import was incorrect for importing within a directory. it should have been from models.User import User, so long as the models/ folder is a module, so all I needed to do then was touch models/__init__.py.