Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python Build a Social Network with Flask Broadcasting Stream Templates

Oisin Kilkenny
Oisin Kilkenny
14,213 Points

Table post has no column named content

After I post something I get an OperationalError saying "Table post has no column named content". I have no idea why it's saying this. I have the exact same code from the videos, I even tried it with the downloaded project files and I get the same error.

I don't know if this is of use, but I'll dump it here in case.

File "C:\Python27\lib\site-packages\flask\app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Python27\lib\site-packages\flask\app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "C:\Python27\lib\site-packages\flask\app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Python27\lib\site-packages\flask\app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "C:\Python27\lib\site-packages\flask\app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Python27\lib\site-packages\flask\app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Python27\lib\site-packages\flask\app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Python27\lib\site-packages\flask\app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Python27\lib\site-packages\flask_login.py", line 758, in decorated_view
return func(*args, **kwargs)
File "U:\python\SocialNetwork\app.py", line 89, in post
content=form.content.data.strip())
File "C:\Python27\lib\site-packages\peewee.py", line 4001, in create
inst.save(force_insert=True)
File "C:\Python27\lib\site-packages\peewee.py", line 4148, in save
pk_from_cursor = self.insert(**field_dict).execute()
File "C:\Python27\lib\site-packages\peewee.py", line 2858, in execute
cursor = self._execute()
File "C:\Python27\lib\site-packages\peewee.py", line 2371, in _execute
return self.database.execute_sql(sql, params, self.require_commit)
File "C:\Python27\lib\site-packages\peewee.py", line 3073, in execute_sql
self.commit()
File "C:\Python27\lib\site-packages\peewee.py", line 2922, in __exit__
Display the sourcecode for this frameOpen an interactive python shell in this framereraise(new_type, new_type(*exc_value.args), traceback)
File "C:\Python27\lib\site-packages\peewee.py", line 3065, in execute_sql
cursor.execute(sql, params or ())

2 Answers

Ken Alger
STAFF
Ken Alger
Treehouse Teacher

Oisin;

The error you are getting indicates that there is an issue with the formation of your database table. If you could post your project files (app.py, models.py, and forms.py) let's see if we can get this sorted out. If you want to get a head start on the rest of us in the forum, take a look at where content is defined and used.

Ken

Oisin Kilkenny
Oisin Kilkenny
14,213 Points

app.py

from flask import (Flask, g, render_template, flash, redirect, url_for)
from flask.ext.bcrypt import check_password_hash
from flask.ext.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 = 'auoesh.bouoastuh.43,uoausoehuosth3ououea.auoub!'

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 the database before each request."""
    g.db = models.DATABASE
    g.db.connect()
    g.user = current_user


@app.after_request
def after_request(response):
    """Close the database 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("Yay, you 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've 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've been logged out! Come back soon!", "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.id,
                           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='OisinKilkenny',
            email='Oisin@email.com',
            password='password',
            admin=True
        )
    except ValueError:
        pass
    app.run(debug=DEBUG, host=HOST, port=PORT)

models.py

import datetime

from flask.ext.bcrypt import generate_password_hash
from flask.ext.login import UserMixin
from peewee import *

DATABASE = SqliteDatabase('social.db', threadlocals=True)

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)
        )

    @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(
        rel_model=User,
        related_name='posts'
    )
    content = TextField()

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


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

forms.py

from flask_wtf import Form
from wtforms import StringField, PasswordField, TextAreaField
from wtforms.validators import (DataRequired, Regexp, ValidationError, Email,
                               Length, EqualTo)

from models import User


def name_exists(form, field):
    if User.select().where(User.username == field.data).exists():
        raise ValidationError('User with that name already exists.')


def email_exists(form, field):
    if User.select().where(User.email == field.data).exists():
        raise ValidationError('User with that email already exists.')


class RegisterForm(Form):
    username = StringField(
        'Username',
        validators=[
            DataRequired(),
            Regexp(
                r'^[a-zA-Z0-9_]+$',
                message=("Username should be one word, letters, "
                         "numbers, and underscores only.")
            ),
            name_exists
        ])
    email = StringField(
        'Email',
        validators=[
            DataRequired(),
            Email(),
            email_exists
        ])
    password = PasswordField(
        'Password',
        validators=[
            DataRequired(),
            Length(min=2),
            EqualTo('password2', message='Passwords must match')
        ])
    password2 = PasswordField(
        'Confirm Password',
        validators=[DataRequired()]
    )


class LoginForm(Form):
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired()])


class PostForm(Form):
    content = TextAreaField("What's up?", validators=[DataRequired()])

I've looked at where content is defined, but can't seem to find my error. :(

Ken Alger
Ken Alger
Treehouse Teacher

Another quick question. Are you doing this on your local machine or in Workspaces?

Oisin Kilkenny
Oisin Kilkenny
14,213 Points

Local machine, running Python 2.7.10

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

Oh, sorry, wrong course.

Sounds like maybe the initialize() didn't run. Can you run it directly? Pop into a Python shell, import the function, and run it. You might want to delete the SQLite database first, even.

Oisin Kilkenny
Oisin Kilkenny
14,213 Points

Where should the database be stored in order to delete it?

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

It should be in the same directory as your Flask app. Should be named social.db.

Oisin Kilkenny
Oisin Kilkenny
14,213 Points

Okay, well I don't have that. I have: app.py, forms.py, forms.pyc, models.py, models.pyc

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

OK, so that's the first problem :) You don't have a database. What happens when you run app.py?

Oisin Kilkenny
Oisin Kilkenny
14,213 Points

I get this error: OperationalError: no such column: t1.content

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

You get an operational error when you do python app.py on your command line?

Oisin Kilkenny
Oisin Kilkenny
14,213 Points

Yes, but I get the message in the browser