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

Keith Doyle
Keith Doyle
25,973 Points

Model.create method not creating user

I'm having some trouble creating a Flask app based off the work done in the Flask course. When I run my app, the database and table are created but the user isn't. I'm using PyCharm IDE like I have with all the other applications and the code checks out just fine with no errors.

models.py

import datetime

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

DATABASE = SqliteDatabase('innovation.db')


class BaseModel(Model):
    class Meta:
        database = DATABASE


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

    class Meta:
        order_by = ('username',)

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


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

app.py

from flask import Flask, g

import models


DEBUG = True
PORT = 5000
HOST = '0.0.0.0'

app = Flask(__name__)
app.secret_key = 'lkuas0df8708792134jkha)*&)*&LKHJSDF98734'


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


@app.after_request
def after_request(response):
    """Connect to the database before each request and return response."""
    g.db.close()
    return response


@app.route('/')
def index():
    return 'Hello World!'


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

1 Answer

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,423 Points

You code is falling into the pit of misdirected exceptions: reraising the database IntegrityError as a ValueError when other issues are present.

Running your code interactively showed unusual behavior:

$ ipython3
Python 3.4.3 (default, Oct 14 2015, 20:28:29) 
Type "copyright", "credits" or "license" for more information.
IPython 1.2.1 -- An enhanced Interactive Python.

In [1]: import models

In [2]: models.initialize()

In [3]: models.User.create_user(username='testuser', password='password', admin=True)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-940256427ed0> in <module>()
----> 1 models.User.create_user(username='testuser', password='password', admin=True)

/home/chrisf/devel/Treehouse/questions/keith-doyle/models.py in create_user(cls, username, password, admin)
     40                     is_admin=admin)
     41         except IntegrityError:
---> 42             raise ValueError("User already exists")
     43 
     44 

ValueError: User already exists

In [4]: models.User.create_user(username='Beeblebrox', password='password', admin=True)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-cf0e6ac158c0> in <module>()
----> 1 models.User.create_user(username='Beeblebrox', password='password', admin=True)

/home/chrisf/devel/Treehouse/questions/keith-doyle/models.py in create_user(cls, username, password, admin)
     40                     is_admin=admin)
     41         except IntegrityError:
---> 42             raise ValueError("User already exists")
     43 
     44 

ValueError: User already exists

That's is weird, let's dig deeper. I comment out the try/except portion in User.create_user() and re-ran:

$ ipython3
Python 3.4.3 (default, Oct 14 2015, 20:28:29) 
Type "copyright", "credits" or "license" for more information.

IPython 1.2.1 -- An enhanced Interactive Python.
In [1]: import models

In [2]: models.User.create_user(username='Beeblebrox', password='password', admin=True)
---------------------------------------------------------------------------
IntegrityError                            Traceback (most recent call last)
<ipython-input-2-cf0e6ac158c0> in <module>()
----> 1 models.User.create_user(username='Beeblebrox', password='password', admin=True)

/home/chrisf/devel/Treehouse/questions/keith-doyle/models.py in create_user(cls, username, password, admin)
     38                     username=username,
     39                     password=generate_password_hash(password),
---> 40                     is_admin=admin)
     41         #except IntegrityError:
     42         #    raise ValueError("User already exists")

/home/chrisf/.virtualenvs/flasksocial/lib/python3.4/site-packages/peewee.py in create(cls, **query)
   4287     def create(cls, **query):
   4288         inst = cls(**query)
-> 4289         inst.save(force_insert=True)
   4290         inst._prepare_instance()
   4291         return inst

/home/chrisf/.virtualenvs/flasksocial/lib/python3.4/site-packages/peewee.py in save(self, force_insert, only)
   4459             rows = self.update(**field_dict).where(self._pk_expr()).execute()
   4460         else:
-> 4461             pk_from_cursor = self.insert(**field_dict).execute()
   4462             if pk_from_cursor is not None:
   4463                 pk_value = pk_from_cursor

/home/chrisf/.virtualenvs/flasksocial/lib/python3.4/site-packages/peewee.py in execute(self)
   3111             return self._qr
   3112         else:
-> 3113             cursor = self._execute()
   3114             if not self._is_multi_row_insert:
   3115                 if self.database.insert_returning:

/home/chrisf/.virtualenvs/flasksocial/lib/python3.4/site-packages/peewee.py in _execute(self)
   2533     def _execute(self):
   2534         sql, params = self.sql()
-> 2535         return self.database.execute_sql(sql, params, self.require_commit)
   2536 
   2537     def execute(self):

/home/chrisf/.virtualenvs/flasksocial/lib/python3.4/site-packages/peewee.py in execute_sql(self, sql, params, require_commit)
   3337             else:
   3338                 if require_commit and self.get_autocommit():
-> 3339                     self.commit()
   3340         return cursor
   3341 

/home/chrisf/.virtualenvs/flasksocial/lib/python3.4/site-packages/peewee.py in __exit__(self, exc_type, exc_value, traceback)
   3183             else:
   3184                 exc_args = exc_value.args
-> 3185             reraise(new_type, new_type(*exc_args), traceback)
   3186 
   3187 class _BaseConnectionLocal(object):

/home/chrisf/.virtualenvs/flasksocial/lib/python3.4/site-packages/peewee.py in reraise(tp, value, tb)
    121     def reraise(tp, value, tb=None):
    122         if value.__traceback__ is not tb:
--> 123             raise value.with_traceback(tb)
    124         raise value
    125 elif PY2:

/home/chrisf/.virtualenvs/flasksocial/lib/python3.4/site-packages/peewee.py in execute_sql(self, sql, params, require_commit)
   3329             cursor = self.get_cursor()
   3330             try:
-> 3331                 cursor.execute(sql, params or ())
   3332             except Exception as exc:
   3333                 if self.get_autocommit() and self.autorollback:

IntegrityError: NOT NULL constraint failed: user.join_date

Now it is clear: There is an issue with the user.join_date field.

It looks like you left off the "default=" in the User field definition:

    joined_at = DateTimeField(default=datetime.datetime.now)
Keith Doyle
Keith Doyle
25,973 Points

Thanks! I'm going to have to look into debugging like that. I really appreciate your help.