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

Yosef Fastow
Yosef Fastow
18,526 Points

Don't know whats wrong with the tacocat program?

Getting a builtins.NameError NameError: name 'username' is not defined

Don't know what is wrong so I posted my code to see if anyone else could see problems!

tacocat.py

from flask import (Flask, g, render_template, flash, redirect, url_for, abort)
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 = 'neiofh23tipQ3RWHGREJFK;SJDWR2I4TG34QW=oglvo0e5ujhynhrjaefpo'

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 == username)
    except models.DoesNotExist:
        return None


@app.before_request
def before_request():
    g.db = models.DATABASE
    g.db.connect()
    g.user = current_user


@app.after_request
def after_request(response):
    g.db.close()
    return response


@app.route('/register', methods=('GET', 'POST'))
def register():
    form = forms.RegisterForm()
    if form.validate_on_submit():
        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!")
        else:
            if check_password_hash(user.password, form.password.data):
                login_user(user)
                flash("You logged in!")
                return redirect(url_for('index'))
            else:
                flash("Your email or password doesn't match!")
    return render_template('login.html', form=form)


@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('index'))


@app.route('/')
def index():
    tacos = models.Taco.select().limit(25)
    return render_template('index.html', index=index, tacos=tacos)


@app.route('/new-taco', methods=('GET', 'POST'))
@login_required
def tacos():
    form = forms.TacoForm()
    if form.validate_on_submit():
        models.Taco.create(user=g.user._get_current_object(),
                            protein=form.protein.data.strip(),
                            shell=form.shell.data.strip(),
                            cheese=form.cheese.data.strip(),
                            extra=form.extra.data.strip())
        return redirect(url_for('index'))
    return render_template('taco.html', form=form)


@app.route('/tacos/<int:taco_id>')
def veiw_tacos(post_id):
    tacos = models.Taco.select().where(models.Taco.id == taco_id)
    if tacos.count() == 0:
        flash("New site sorry We will have stuff on soon you could make the first post!")
    return render_template('index.html', tacos=tacos)









if __name__ == '__main__':
    models.initialize()
    app.run(debug=DEBUG, host=HOST, port=PORT)

forms.py

from flask_wtf import Form
from wtforms import StringField, PasswordField, TextAreaField, BooleanField
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 allready exists.")


def email_exists(form, field):
    if User.select().where(User.email == field.data).exists():
        raise ValidatorsError("User with that email allready 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=4),
            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 TacoForm(Form):
    protein = StringField("What type of protein is in your taco? Beans? Beef?", validators=[DataRequired()])
    shell = StringField("What type of shell is your taco?", validators=[DataRequired()])
    cheese = BooleanField("Cheese", default=True)
    extras = TextAreaField("Add any other detail.", validators=[DataRequired()])

models.py

import datetime

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

DATABASE = SqliteDatabase('tacocat.db')

class User(UserMixin, Model):
    username = CharField(unique=True)
    email = CharField(unique=True)
    password = CharField(max_length=100)

    class Meta:
        database = DATABASE

    @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 allready exists")


class Taco(Model):
    timestamp = DateTimeField(default=datetime.datetime.now)
    user = ForeignKeyField(
        rel_model=User,
        related_name='tacos'
    )
    protein = CharField(max_length=25)
    shell = CharField(max_length=25)
    cheese = BooleanField()
    extras = TextField()

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






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

index.html

{% extends 'layout.html' %}

{% block content %}
<h2>Tacos</h2>
    {% if tacos.count() %}
        <table class="u-full-width">
          <thead>
            <tr>
              <th>Protein</th>
              <th>Cheese?</th>
              <th>Shell</th>
              <th>Extras</th>
            </tr>
          </thead>
          <tbody>
        {% for taco in tacos %}
            <tr>
              <!-- taco attributes here -->
                {{ taco.protein }}
                {{ taco.cheese }}
                {{ taco.shells }}
                {{ taco.extras }}
            </tr>
        {% endfor %}
          </tbody>
        </table>
    {% else %}
        <!-- message for missing tacos -->
        <p>Sorry the site is new and empty pleases add and help us start our site!</p>
    {% endif %}
{% endblock %}

layout.html

<!doctype html>
<html>
  <head>
    <title>Tacocat</title>
    <link rel="stylesheet" href="/static/css/normalize.css">
    <link rel="stylesheet" href="/static/css/skeleton.css">
    <link rel="stylesheet" href="/static/css/tacocat.css">
  </head>
  <body>
    {% with messages=get_flashed_messages() %}
    {% if messages %}
        <div class="messages">
          {% for message in messages %}
          <div class="message">
            {{ message }}
          </div>
          {% endfor %}
        </div>
    {% endif %}
    {% endwith %}

    <div class="container">
      <div class="row">
        <div class="u-full-width">
          <nav class="menu">
          <!-- menu goes here -->
              {% if current_user.is_authenticated %}
                  <h5><a href="http://port-8000-bkvi3xbmhb.treehouse-app.com/logout"></a>Logout!</h5>
                  <h5><a href="http://port-8000-bkvi3xbmhb.treehouse-app.com/new-taco"></a>Add your taco!</h5>
              {% else %}
                  <h5><a href="http://port-8000-bkvi3xbmhb.treehouse-app.com/login"></a>Login!</h5>
                  <h5><a href="http://port-8000-bkvi3xbmhb.treehouse-app.com/register">SignUp!</a></h5>
              {% endif %}
          </nav>
          {% block content %}{% endblock %}
        </div>
      </div>
      <footer>
        <p>An MVP web app made with Flask on <a href="http://teamtreehouse.com">Treehouse</a>.</p>
      </footer>
    </div>
  </body>
</html>

1 Answer

Sean T. Unwin
Sean T. Unwin
28,690 Points

In forms.py the defined functions, name_exists() and email_exists() when called from within the class RegisterForm do not have brackets nor are parameters given ( there are 2 parameters in the function declarations ).

Disclaimer: I have only read the code, not run it.

Aside: The word, 'already' only has one (1) 'L'. Check the validation messages in forms.py and models.py for the typos. :)