Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Ryan Mooney
seal-mask
.a{fill-rule:evenodd;}techdegree
Ryan Mooney
Data Analysis Techdegree Student 14,265 Points

KeyError with the class Relationship(Model)

I am running this on my local computer instead of through workspaces. I have found a few changes I needed to make such as "related_name" is now "backref" (due to the updated version of peewee. So far, I cannot figure out why I am getting a system breaking error. Here is the full error from the command line:

Traceback (most recent call last): File "app.py", line 111, in <module> models.initialize() File "D:\Programming\Python\teamTreehouse\flaskSocial\venv\models.py", line 86, in initialize DATABASE.create_tables([User, Post, Relationship], safe=True) File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 3286, in create_ tables model.create_table(options) File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 6595, in create_ table cls.schema.create_all(safe, **options) File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 5732, in create all self.create_indexes(safe=safe) File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 5645, in create_ indexes for query in self.create_indexes(safe=safe): File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 5634, in _create _indexes for index in self.model._meta.fields_to_index()] File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 6011, in fields to_index fields.append(self.combined[part]) KeyError: 'f' PS D:\Programming\Python\teamTreehouse\flaskSocial\venv> python app.py Traceback (most recent call last): File "app.py", line 111, in <module> models.initialize() File "D:\Programming\Python\teamTreehouse\flaskSocial\venv\models.py", line 86, in initialize DATABASE.create_tables([User, Post, Relationship], safe=True) File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 3286, in create_ tables model.create_table(options) File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 6595, in create_ table cls.schema.create_all(safe, **options) File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 5732, in create all self.create_indexes(safe=safe) File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 5645, in create_ indexes for query in self.create_indexes(safe=safe): File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 5634, in _create _indexes for index in self.model._meta.fields_to_index()] File "d:\Programming\Python\teamTreehouse\flaskSocial\venv\lib\site-packages\peewee.py", line 6011, in fields to_index fields.append(self.combined[part]) KeyError: 'f'

Here is my models.py file: import datetime

from flask_bcrypt import generate_password_hash from flask_bcrypt import check_password_hash from flask_login import UserMixin from peewee import *

DATABASE = SqliteDatabase('social.db')

class User(UserMixin, Model): username = CharField(unique=True) email = CharField(unique=True) password = CharField(max_length=100) joined_at = DateTimeField(default=datetime.datetime.now) is_admin = BooleanField(default=False)

class Meta:
    database = DATABASE
    order_by = ('-joined_at',)

def get_posts(self):
    return Post.select().where(Post.user == self)

def get_stream(self):
    return Post.select().where(
        (Post.user == self)
    )

def following(self):
    """The users that we are following."""
    return (
        User.select().join(
            Relationship, on=Relationship.to_user
        ).where(
            Relationship.from_user == self
        )
    )

def followers(self):
    """Get Users following the current user"""
    return (
        User.select().join(
            Relationship, on=Relationship.from_user
        ).where(
            Relationship.to_user == self
        )
    )

@classmethod
def create_user(cls, username, email, password, admin=False):
    try:
        with DATABASE.transaction():
            cls.create(
                username = username,
                email = email,
                password = generate_password_hash(password),
                is_admin = admin
            )
    except IntegrityError:
        raise ValueError ("User already exists")

class Post(Model): timestamp = DateTimeField(default=datetime.datetime.now) user = ForeignKeyField( model=User, backref='posts' ) content = TextField()

class Meta:
    database = DATABASE
    order_by = ('-timestamp',)

class Relationship(Model): from_user = ForeignKeyField(User, backref='relationships') to_user = ForeignKeyField(User, backref='related_to')

class Meta:
    database = DATABASE
    indexes = (
        (('from_user', 'to_user'), True)
    )

def initialize(): DATABASE.connect() DATABASE.create_tables([User, Post, Relationship], safe=True) DATABASE.close()

I have compared this to the actual PeeWee docs (http://docs.peewee-orm.com/en/latest/peewee/models.html#single-column-indexes-and-constraints) but cannot find the error. Everything appears to be properly strucutured

Josh Keenan
Josh Keenan
20,315 Points

Can you put three backtick ` characters at the start and end of the code please. And could you add your app.py too

Ryan Mooney
seal-mask
.a{fill-rule:evenodd;}techdegree
Ryan Mooney
Data Analysis Techdegree Student 14,265 Points

sorry, here you go

models.py

import datetime

from flask_bcrypt import generate_password_hash
from flask_bcrypt import check_password_hash
from flask_login import UserMixin
from peewee import *

DATABASE = SqliteDatabase('social.db')

class User(UserMixin, Model):
    username = CharField(unique=True)
    email = CharField(unique=True)
    password = CharField(max_length=100)
    joined_at = DateTimeField(default=datetime.datetime.now)
    is_admin = BooleanField(default=False)

    class Meta:
        database = DATABASE
        order_by = ('-joined_at',)

    def get_posts(self):
        return Post.select().where(Post.user == self)

    def get_stream(self):
        return Post.select().where(
            (Post.user == self)
        )

    def following(self):
        """The users that we are following."""
        return (
            User.select().join(
                Relationship, on=Relationship.to_user
            ).where(
                Relationship.from_user == self
            )
        )

    def followers(self):
        """Get Users following the current user"""
        return (
            User.select().join(
                Relationship, on=Relationship.from_user
            ).where(
                Relationship.to_user == self
            )
        )

    @classmethod
    def create_user(cls, username, email, password, admin=False):
        try:
            with DATABASE.transaction():
                cls.create(
                    username = username,
                    email = email,
                    password = generate_password_hash(password),
                    is_admin = admin
                )
        except IntegrityError:
            raise ValueError ("User already exists")

class Post(Model):
    timestamp = DateTimeField(default=datetime.datetime.now)
    user = ForeignKeyField(
        model=User,
        backref='posts'
    )
    content = TextField()

    class Meta:
        database = DATABASE
        order_by = ('-timestamp',)

class Relationship(Model):
    from_user = ForeignKeyField(User, backref='relationships')
    to_user = ForeignKeyField(User, backref='related_to')

    class Meta:
        database = DATABASE
        indexes = (
            (('from_user', 'to_user'), True)
        )

def initialize():
    DATABASE.connect()
    DATABASE.create_tables([User, Post, Relationship], safe=True)
    DATABASE.close()

app.py

from flask import (Flask, g, render_template, flash,
                   redirect, url_for)
from flask_bcrypt import check_password_hash
from flask_login import (LoginManager, login_user, logout_user,
                         login_required, current_user)

import forms
import models

DEBUG = True
PORT = 8000
HOST = "0.0.0.0"

app = Flask(__name__)
app.secret_key = 'xVQFFPq798Z6JejNkfxHS'

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

@login_manager.user_loader
def load_user(userid):
    try:
        return models.User.get(models.User.id == userid)
    except models.DoesNotExist:
        return None

@app.before_request
def before_request():
    """Connect to DB before each request"""
    g.db = models.DATABASE
    g.db.connect()
    g.user = current_user


@app.after_request
def after_request(response):
    """Close the DB Connection after each request"""
    g.db.close()
    return response

@app.route('/register', methods=('GET', 'POST'))
def register():
    form = forms.RegisterForm()
    if form.validate_on_submit():
        flash("You have successfully registered!", 'success')
        models.User.create_user(
            username = form.username.data,
            email = form.email.data,
            password= form. password.data
        )
        return redirect(url_for('index'))
    return render_template('register.html', form=form)

@app.route('/login', methods=('GET', 'POST'))
def login():
    form = forms.LoginForm()
    if form.validate_on_submit():
        try:
            user = models.User.get(models.User.email == form.email.data)
        except models.DoesNotExist:
            flash("Your email or password doesn't match!", 'error')
        else:
            if check_password_hash(user.password, form.password.data):
                login_user(user)
                flash('You have been logged in!', 'success')
                return redirect(url_for('index'))
            else:
                flash("Your email or password doesn't match!", 'error')
    return render_template('login.html', form=form)

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash("You have been logged out!", 'success')
    return redirect(url_for('index'))

@app.route('/new_post', methods=('GET', 'POST'))
@login_required
def post():
    form = forms.PostForm()
    if form.validate_on_submit():
        models.Post.create(user=g.user._get_current_object(),
                           content = form.content.data.strip())
        flash("Message Posted! Thanks!", "success")
        return redirect(url_for('index'))
    return render_template('post.html', form=form)


@app.route('/')
def index():
    stream = models.Post.select().limit(100)
    return render_template('stream.html', stream=stream)

@app.route('/stream')
@app.route('/stream/<username>')
def stream(username=None):
    template = 'stream.html'
    if username and username != current_user.username:
        user=models.User.select().where(models.User.username**username).get()
        stream = user.posts.limit(100)
    else:
        stream = current_user.get_stream().limit(100)
        user = current_user  
    if username:
        template = 'user_stream.html'
    return render_template(template, stream=stream, user=user)

if __name__ == '__main__':
    models.initialize()
    try:
        models.User.create_user(
            username='ryan',
            email='ryan@ryan.com',
            password='password',
            admin=True
        )
    except ValueError:
        pass
    app.run(debug=DEBUG, port=PORT, host=HOST)

I did rerun through the code. If I remove the "Relationship" from the DATABASE.create_tables, it runs fine. That leads me to believe there is something wrong with the Relationship class.

Up to this point, any variation from the course (due to version changes of PeeWee), was easily found in the PeeWee docs as mentioned in my original post. I am truly stumped.