I have a problem with Flask and Flask-SQLAlchemy where for any query I would need to import all the related models.
Now my auth.views.py looks like this (first few lines of programming this thing so just a test view)
from flask import jsonify
from . import auth
from app.models.user import User
@auth.route('/', methods=['GET'])
def index():
users = User.query.all()
return jsonify({'name': users[0].name})
Now I'm getting an error
"InvalidRequestError: When initializing mapper Mapper|User|user, expression 'Course' failed to locate a name ("name 'Course' is not defined"). If this is a class name, consider adding this relationship() to the class after both dependent classes have been defined."
I have a project where i have a models package like so
app
├── auth
│ ├── __init__.py
│ └── views.py
├── __init__.py
└── models
├── assignment.py
├── base.py
├── client.py
├── course.py
├── __init__.py
├── submission.py
└── user.py
my user class has a many to many with Course and a one to many with Submission.
This is solved by importing the Course (and then Submission, and then the relations from there, eventually all the models basically.)
At work for Pyramid projects we also work with SQLAlchemy but I never have to import all the models to do my work. Any ideas whats up? I really can't figure this out and I haven't been able to google it.
User looks like this
user_course = db.Table(
'user_course', db.Model.metadata,
db.Column('student_id', UUID, db.ForeignKey('user.id'),
primary_key=True),
db.Column('course_id', UUID, db.ForeignKey('course.id'),
primary_key=True)
)
class User(db.Model):
id = db.Column(UUID, default=lambda: str(uuid.uuid4()), primary_key=True)
firstname = db.Column(db.String(100), nullable=False)
lastname = db.Column(db.String(100), nullable=False)
insertion = db.Column(db.String(15)) # tussenvoegsel
# email = db.Column(db.String, nullable=False, unique=True)
password_hash = db.Column(db.String, nullable=False)
enrolled_courses = db.relationship('Course', secondary=user_course,
backref='students')
managed_courses = db.relationship('Course', backref='teacher')
submissions = db.relationship('Submission', backref='student')
@property
def name(self):
return "{}{}{}".format(
self.firstname + " ",
self.insertion + " " if self.insertion else "",
self.lastname
)
@property
def password(self):
raise AttributeError("Password is not a readable attribute")
@password.setter
def password(self, password):
self.password_hash = bcrypt.hashpw(password, bcrypt.gensalt(12))
def verify_password(self, password):
return bcrypt.hashpw(password, self.password_hash) == \
self.password_hash
If you really want to stick to the one-file-per-class scheme, in my opionion, the cleaner option would be to do the imports in the model package's init:
models/__init__.py:
from user import User
from client import Client
from course import Course
# plus your remaining classes
Then you can import the classes as
from models import User
which makes things more readable and would allow to mix the one-file-per-class scheme with modules containing multiple classes, while still being able to import all classes in a "flat" manner from models
.