-1

I'm creating my first Flask project. The first part of the project is obviusly the login part. I made with html tho page for sign up and login. Then I wrote the flask part of the project. The code is the following, divided in the main.py file

from flask import Flask, render_template, redirect, url_for, session
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine
from os import path
from flask_login import LoginManager

db = SQLAlchemy()
DB_NAME = "database.db"

def create_app():
    app = Flask(__name__,static_url_path='/static')
    app.secret_key = "referendumKey"
    app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
    db.init_app(app)

    #importation of all blueprints created
    from .auth import auth
    from .views import views

    app.register_blueprint(auth, url_prefix='/')
    app.register_blueprint(views, url_prefix='/')

    #model import

    from .models import Refs, User

    create_database(app)

    login_manager = LoginManager()
    login_manager.login_view = 'auth.login'
    login_manager.init_app(app)

    @login_manager.user_loader
    def load_user(id):
        return User.query.get(int(id))

    return app

#If you haven't already created a database, it will be created
def create_database(app):
    if not path.exists('website/' + DB_NAME):
        db.create_all(app=app)
        print('Created Database!')

Then, the authentication file (auth.py)

from flask import Blueprint, render_template, session, redirect, url_for, request, flash
from .models import User
from . import db
from flask_login import login_user, login_required, logout_user, current_user

auth = Blueprint("auth", __name__)

@auth.route("/login", methods=["GET", "POST"])
def login():
    if request.method == 'POST':
        name =request.form.get("username")
        psw =request.form.get("psw")
        user = User.query.filter_by(name=name).first()
        if user:
            if psw == user.password:
                flash("Logged succesfully", category="success")
                login_user(user, remember=True)
                return redirect(url_for("views.home"))
            else:
                flash("Incorrect password", category="error")
        else:
            flash("Unexistent user", category="error")
    return render_template("login.html", user=current_user)


@auth.route("/signup", methods=["GET", "POST"])
def signup():
    if request.method=="POST":
        username=request.form.get('username')
        psw1=request.form.get('psw1')
        psw2=request.form.get('psw2')

        user = User.query.filter_by(name=username).first()
        if user:
            flash("Username already exist", category="error")
        elif len(username)<3:
            flash("Username too short", category="error")
        elif psw1!=psw2:
            flash("Passwords are different", category="error")
        else:
            new_user = User(name=username, password=psw1)
            db.session.add(new_user)
            db.session.commit()
            login_user(new_user, remember=True)
            flash("Account created", category="Success")
            return redirect(url_for(views.home))
    return render_template("signup.html", user=current_user)

@auth.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('auth.login'))

And, the views.py file, that should let people see the home page with content

  
from flask import Blueprint, render_template, request, flash, jsonify
from flask_login import login_required, current_user
from . import db

views = Blueprint('views', __name__)

@views.route("/")
@views.route("/home")
@login_required
def home():
    return render_template("home.html")

To store the datatypes, I used the models in the following code

from . import db
from flask_login import UserMixin
from sqlalchemy.sql import func

"""
Definire la classe che identidica un Referendum, inserendovi:
id di colonna, la domanda, la prima e la seconda risposta 
possibili, i voti che hanno ricevuto, chi ha votato già, l'id
dell'utente che possiede il ref
"""
class Refs(db.Model):
    id = db.Column(db.Integer,primary_key=True)
    question = db.Column(db.String(200))
    fAnsw = db.Column(db.String(200))
    sAnsw = db.Column(db.String(200))
    fVote = db.Column(db.Integer, default=0)
    sVote = db.Column(db.Integer, default=0)
    voters = db.Column(db.ARRAY(db.Integer))
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))


"""
Definire la classe utente inserendo il suo nome, la sua 
password, e tutti i Referendum da lui creato
"""
class User(db.Model,UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), unique=True)
    password = db.Column(db.String(150))
    refs = db.relationship('Refs')

Now, there is a problem. If I try to create a new account, or to login, there is an error. The error is the following one.

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: user
[SQL: SELECT user.id AS user_id, user.name AS user_name, user.password AS user_password 
FROM user 
WHERE user.name = ?
 LIMIT ? OFFSET ?]
[parameters: ('sadas', 1, 0)]
(Background on this error at: http://sqlalche.me/e/14/e3q8)

And it shows the follow part of the code:

user = User.query.filter_by(name=name).first()

I guess the problem is in the model of the database, because it shows up a SQLAlchemy error. Probably I used an incorrect syntax. I read a lot of github repository, and also the official documentation (https://docs.sqlalchemy.org/en/14/),and even the link relased by the compiler, but I can't understand, I think I wrote it correctly. The error can even be in the flask_login API usage, but reading error and documentation I guess it isn't. Can someone help me please? Thanks

2
  • are you sure you created the database because the error says there is no table named user. Commented Jun 7, 2021 at 20:27
  • The database is created. It exist a db file in the same directory of the file .py. So... Commented Jun 8, 2021 at 17:30

2 Answers 2

0

Creating a database at runtime is not preferred. Flask app needs to be connected to a database on start. You may create tables at runtime.

Sign up to request clarification or add additional context in comments.

2 Comments

Ok, so, where is the point into I should put the code to create the datatabase? Isn't enought the line into I say db.init_app(app) in the first file? Or I need something more?
Yes, you're using SQLAlchemy. So, from yourapplication import db and db.create_all() should work
0

I suspect that you created an empty database somewhere. So the DB file may exist but contain no tables. You may in fact have two lingering SQLite files at different locations. Inspect your directories carefully.

Consider this code:

DB_NAME = "database.db"

def create_app():
    app = Flask(__name__,static_url_path='/static')
    app.secret_key = "referendumKey"
    app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'

This will create a SQLite file in the "current" directory (whatever it is).

Elsewhere you specify a relative path - again, it's not clear what the final path is but could very well be different than above:

def create_database(app):
    if not path.exists('website/' + DB_NAME):
        db.create_all(app=app)
        print('Created Database!')

The fix is to use a fully qualified path for your DB, not a relative path.

2 Comments

It seems true, but I read some Github repositories, and one of those uses the same code I used, and there aren't errors. Go to the init.py file of this repository. Maybe I understood uncorrectly what you mean, but I don't think so. Repo: github.com/techwithtim/Flask-Web-App-Tutorial/blob/main/website/…
I tried to change. If I wrote in both "website/+DB_NAME and only DB_NAME . Now it works. Thank you so much

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.