Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask + SQLAlchemy: Class not Iterable

I am having a problem when trying to render a SQLAlchemy query into a template, the error I get is:

TypeError: 'Users' object is not iterable

The DB is a sqlite
I have been following the "Discover Real Python" tutorial on youtube and it has been a big help. The only things i have changed is in the tutorial he uses "BlogPosts", and I use "Users"

I am trying to understand how he got users to iterate in his version of the code in the template.

My Models.py file is this:

from app import db

class Users(db.Model):
    __tablename__="users"

    id= db.Column(db.Integer, primary_key=True)
    username=db.Column(db.String, nullable=False)
    password=db.Column(db.String, nullable=False)

    def __init__(self, username, password):
        self.username=username
        self.password=password

    def __repr__(self):
        return '<username{}'.format(self.username)

and my "app.py" file.

from flask import Flask, render_template, redirect, url_for, request, session, flash
from functools import wraps
#import sqlite3
from flask.ext.sqlalchemy import SQLAlchemy


app= Flask(__name__)

app.secret_key="this is the secret key"
#app.database="users.db"

app.config['SQLALCHEMY_DATABASE_URI']='sqlite:////users2.db'

db=SQLAlchemy(app)

from models import *

def login_required(f):
    @wraps(f)
    def wrap(*args, **kwargs):
        if 'logged_in' in session:
            return f(*args, **kwargs)
        else:
            flash('You must be logged in to complete this action')
            return redirect(url_for('login'))
    return wrap


@app.route('/')
def index():
    users= db.session.query(Users).all()
    return render_template('index.html', users=users)


@app.route('/testing')
def testing():
    users= db.session.query(Users).all()
    return render_template('testquery.html', users=users)


@app.route('/welcome')
def welcome():
    return render_template('index.html')


@app.route('/login', methods =['GET', 'POST'])
def login():
    error= None
    #form = LoginForm(request.form)
    if request.method == 'POST':
    #if request.form.validate_on_submit():
        if request.form['username'] !='admin' or request.form['password'] !='admin':
            error= 'invalid credentials'
        else:
            session ['logged_in']=True
            flash('login successful')
            return redirect(url_for('loggedin'))
    #else:
        #render_template('login.html', form=form, error=error)
    return render_template('login.html', error=error)


@app.route('/loggedin')
@login_required
def loggedin():
    return render_template('loggedin.html')


@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    flash('You have been logged out')
    return redirect(url_for('welcome'))


#def connect_db():
#   return sqlite3.connect(app.database)

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

The method I have been using to text is the route of "/testing", the testquery.html file is what I have been trying to test with, and have been getting the error with.

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
    <body>


        <table>
        {%for user in users%}
            <tr>
                <td>{{user.username}}</td>
                <td>{{user.password}}</td>
            </tr>

        </table>
        {%endfor%}

    </body>
</html>

I tried the fix i saw in another stack question:

def __init__(self, username, password):
    self.username=[username]
    self.password=[password]

To no avail, this changed nothing. Anyone have any idea what I need to do to make it iterable.

like image 628
TheTimes Avatar asked Dec 08 '14 21:12

TheTimes


People also ask

What are the disadvantages of flask-SQLAlchemy?

Another disadvantage is that Flask-SQLAlchemy makes using the database outside of a Flask context difficult. This is because, with Flask-SQLAlchemy, the database connection, models, and app are all located within the app.py file. Having models within the app file, we have limited ability to interact with the database outside of the app.

Should I use flask or SQLAlchemy for database sessions?

With the proper implementation of sessionmaker and scoped_session, your Flask app should not have any threading issues that arise when connecting to a database across your routes. So when struggling with threading and database sessions, use Flask and SQLAlchemy, not Flask-SQLAlchemy!

Why can’t i load data outside of my flask-SQLAlchemy app?

This is because, with Flask-SQLAlchemy, the database connection, models, and app are all located within the app.py file. Having models within the app file, we have limited ability to interact with the database outside of the app. This makes loading data outside of your app difficult.

How do I create a SQLAlchemy object in flask?

app=Flask(__name__)db=SQLAlchemy(app) The second possibility is to create the object once and configure the application later to support it: db=SQLAlchemy()defcreate_app():app=Flask(__name__)db.init_app(app)returnapp


1 Answers

In testing, you don't have a list of users. You have one user here:

users = db.session.query(Users).first()

This returns just the first user in your database. As such, you cannot loop over the user either. Rename that to user (dropping the s) and remove the loop in your template:

@app.route('/testing')
def testing():
    user = db.session.query(Users).first()
    return render_template('testquery.html', user=user)

and

<table>
  <tr>
    <td>{{user.username}}</td>
    <td>{{user.password}}</td>
  </tr>
</table>
like image 132
Martijn Pieters Avatar answered Oct 27 '22 11:10

Martijn Pieters