Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
437 views
in Technique[技术] by (71.8m points)

python - Flask with models split into multiple files, how to prevent circular imports?

I'm having an issue with circular imports, and I'm not sure how to restructure my code to overcome it.

Say I have the structure

├── app
│   ├──__init__.py
│   ├── models_one.py
│   ├── models_two.py

With models_one.py being the following:

from . import db
from .models_two import Post

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    posts = db.relationship("Post")

    def get_user_posts_with_content(self, passed_content):
        return Post.query.filter(Post.user_id==self.id, Post.content==passed_content).all()

And models_two.py being the following:

from . import db
from .models_one import User

class Post(db.Model):
    __tablename__ = 'posts'
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String(64))
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)

    def get_user(self):
        return User.query.filter(User.id == self.user_id).first()

This creates a circular import, is there a way to do this without having both classes in the same file? If I had both in a models.py this would work, but for a larger project with 30 models I need a better way to segment them all.

I know that you can get all "posts" in this example by calling User.posts, but in the User model you can see how I use a passed variable as part of the query, my project uses quite a bit of this sort of thing.

I'm also aware that it's because within both classes I have a function that calls a query on the other object, but this simplifies some of the template rendering rather than having to load the data within the view first (unless there's something I'm missing with web development, which is VERY possible).

Thanks for any advice you can give, and sorry if this is a simple question, I've read through the O'Reilly book on Flask Web Development and tackled some simpler projects, but I don't understand this well enough even with a day of googling.

question from:https://stackoverflow.com/questions/65836050/flask-with-models-split-into-multiple-files-how-to-prevent-circular-imports

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I found this artical. Maybe this helps you. But what the page basically says is, to merge all into one file, so I guess there is no way to do this how you want to do it. But maybe you can delete the methods from the class and insert them into a third module. So basically:

modules_one:

from . import db

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    posts = db.relationship("Post")

modules_two:

from . import db

class Post(db.Model):
    __tablename__ = 'posts'
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String(64))
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)

moduels_three:

from .models_one import User
from .models_two import Post

def get_user_posts_with_content(self, passed_content):
    return Post.query.filter(Post.user_id==self.id, Post.content==passed_content).all()

def get_user(self):
    return User.query.filter(User.id == self.user_id).first()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...