2

I get an error when I try to import the "User" model in flask_app (which contains app), I am getting ImportError: cannot import name 'User' from 'models' error.

forms.py - I am trying to import User from flask_app

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from flask_app import User


class RegistrationForm(FlaskForm):
    username = StringField('Username',
                           validators=[DataRequired(), Length(min=2, max=20)])
    email = StringField('Email',
                        validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired()])
    confirm_password = PasswordField('Confirm Password',
                                     validators=[DataRequired(), EqualTo('password')])
    submit = SubmitField('Sign Up')

    def validate_username(self, username):
        user = User.query.filter_by(username=username.data).first()
        if user:
            raise ValidationError('That username is taken. Please choose a different one.')

    def validate_email(self, email):
        user = User.query.filter_by(email=email.data).first()
        if user:
            raise ValidationError('That email is taken. Please choose a different one.')

Here is the User model:

from datetime import datetime
from flask import Flask, render_template, url_for, flash, redirect
from flask_sqlalchemy import SQLAlchemy
from forms import RegistrationForm, LoginForm
from flask_bcrypt import Bcrypt
from flask_login import login_user, current_user, logout_user, login_required, LoginManager

app = Flask(__name__)
app.config['SECRET_KEY'] = ''
app.config['SQLALCHEMY_DATABASE_URI'] = ''
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
    password = db.Column(db.String(60), nullable=False)
    posts = db.relationship('Post', backref='author', lazy=True)

    def __repr__(self):
        return f"User('{self.username}', '{self.email}', '{self.image_file}')"


@app.route("/")
@app.route("/home")
def home():
    return render_template('home.html', posts=posts)


if __name__ == '__main__':
    app.run(debug=True)

gives me this:

2020-01-12 08:58:53,282: Error running WSGI application
2020-01-12 08:58:53,284: ImportError: cannot import name 'User' from 'models' (/home/kickie/mysite/models.py)
2020-01-12 08:58:53,287:   File "/var/www/fdfdfd_pythonanywhere_com_wsgi.py", line 16, in <module>
2020-01-12 08:58:53,289:     from flask_app import app as application  # noqa
2020-01-12 08:58:53,290: 
2020-01-12 08:58:53,291:   File "/home/kickie/mysite/flask_app.py", line 4, in <module>
2020-01-12 08:58:53,292:     from forms import RegistrationForm, LoginForm
2020-01-12 08:58:53,292: 
2020-01-12 08:58:53,293:   File "/home/kickie/mysite/forms.py", line 4, in <module>
2020-01-12 08:58:53,293:     from flask_app import User

I'm getting an error because the app is here? Should I move the User to another location?

1 Answer 1

1

This happens because you are doing a circular import

# inside flask_app.py
from forms import RegistrationForm

and

# inside forms.py
from flask_app import User

Check this explanation


Simple Solution

to avoid this problem in your code, if you are deciding to go with this structure

1) just remove the from flask_app import User from forms.py

2) import it inside the methods that are using the Model.

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
# REMOVE THE IMPORT


class RegistrationForm(FlaskForm):
    username = StringField('Username',
                           validators=[DataRequired(), Length(min=2, max=20)])
    email = StringField('Email',
                        validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired()])
    confirm_password = PasswordField('Confirm Password',
                                     validators=[DataRequired(), EqualTo('password')])
    submit = SubmitField('Sign Up')

    def validate_username(self, username):
        # Import them inside the methods that are using the Model
        from flask_app import User
        user = User.query.filter_by(username=username.data).first()
        if user:
            raise ValidationError('That username is taken. Please choose a different one.')

    def validate_email(self, email):
        # Import them inside the methods that are using the Model
        from flask_app import User
        user = User.query.filter_by(email=email.data).first()
        if user:
            raise ValidationError('That email is taken. Please choose a different one.')
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.