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

Social network in flask error, login and register

jinja2.exceptions.TemplateSyntaxError: expected token 'end of print statement', got 'string'

Just started the new treehouse workspace and since using it I have had so many issues, none of which came up for Kenneth so I am confused. This is the bug I have when I try and run the code, no clue what to do...

https://teamtreehouse.com/community/social-network-in-flask-login-error

all my code can be found on that link

That link seems to be broken. If your code is in your workspace you can fork it and post the forked link. It can be found in your workspace home page beside each project right next to workspace setting.

Chris Freeman
Chris Freeman
Treehouse Moderator 68,468 Points

Can you post the code to the template being accessed? The link above only has the base layout.html

13 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,468 Points

Look at your block tags in the rendered template. Make sure they are all of the form:

{% block content %}
{% endblock  %}

Without quotation marks around content.

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,468 Points

As I expected, looking at your login.html, remove the quotation marks from around the word content:

{% extends "layout.html" %} {% from 'macros.html' import render_field %}

{% block content %} {# fix this line #}

{{ form.hidden_tag() }}
{% for field in form %}
    {{ render_field(field) }}
{% endfor %}
<button type="submit" id="submit">Login!</button>

{% endblock %}

It looks like you need to remove the quotes from content in your layout.html and register.html as well.

Haha, I'll try to find it but I unfollowed it

Chris Freeman
Chris Freeman
Treehouse Moderator 68,468 Points

Josh Keenan, please send me a personal email to chris dot freeman dot PDX at gmail dot com. I have a question for you about recently deleted posts.

Code is further down the page I linked you to, and now after adding quotes I have a new issue.

jinja2.exceptions.TemplateSyntaxError: expected token 'name', got 'string'

Chris Freeman
Chris Freeman
Treehouse Moderator 68,468 Points

Can you say what you are doing when this error shows up? Is it during the python app.py execution? Is it seen when visiting a specific URL? Is the error in the console window or in the browser window?

The only template I see is your layout.html. I don't see a template that is called by the view and extends layout

macros.html

{% macro render_field(field) %}
    <div class="field">
        {% if field.errors %}
            {% for error in field.errors %}
                <div class="notification error">{{ error }}</div>
            {% endfor %}
        {% endif %}
        {{ field(placeholder=field.label.text) }}
    </div>
{% endmacro %}

macros.html

<!DOCTYPE html> <html class="no-js"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>{% block title %}TwoCans{% endblock %}</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href='http://fonts.googleapis.com/css?family=Varela+Round' rel='stylesheet' type='text/css'> <link rel="stylesheet" href="/static/css/normalize.min.css"> <link rel="stylesheet" href="/static/css/main.css">

    <!--[if lt IE 9]>
        <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <script>window.html5 || document.write('<script src="/static/js/vendor/html5shiv.js"><\/script>')</script>
    <![endif]-->
</head>
<body>

    <header>

      <div class="row">

        <div class="grid-33">

          <a href="{{ url_for('index') }}" class="icon-logo"></a>

        </div>

        <div class="grid-33">

            <!-- Say Hi -->
            <h1>Hello{% if current_user.is_authenticated() %} {{ current_user.username }}{% endif %}!</h1>  

        </div>

        <div class="grid-33">

            <!-- Log in/Log out -->
            {% if current_user.is_authenticated() %}
               <a href="{{ url_for('logout')" class="icon-power" title="Log out"></a>
            {% else %}
                <a href="{{ url_for('login' )" class="icon-power" title="Log in"></a>
                <a href="{{ url_for('register')" class="icon-profile " title="Register"></a>
            {% endif %}  

        </div>

      </div>

    </header>

    <!-- Flash messages -->
    {% with messages = get_flashed_messages(with_categories=True) %}
        {% if messages %}
            {% for category, message in messages %}
                <div class="notification {{ category }}">{{ message }}</div>
            {% endfor %}
        {% endif %}
    {% endwith %}

    <div class="row">

      <div class="main">

        <nav>

          <a href="{{ url_for('index') }}">All</a>

        </nav>

        {% block 'content' %}{% endblock %}

      </div>

    </div>

    <footer>

      <div class="row">

        <p>A Social App built with Flask<br>by <a href="http://teamtreehouse.com">Treehouse</a></p>

      </div>

    </footer>

    <script src="/static/js/vendor/disTime.min.js"></script>
    <script src="/static/js/main.js"></script>

</body>

</html>

layout.html

{% extends "layout.html" %}
{% from 'macros.html' import render_field %}

{% block 'content' %}
<form method="POST" action="" class="form">
    {{ form.hidden_tag() }}
    {% for field in form %}
        {{ render_field(field) }}
    {% endfor %}
    <button type="submit" id="submit">Register!</button>
</form>
{% endblock %}

register.html

{% extends "layout.html" %}
{% from 'macros.html' import render_field %}

{% block 'content' %}
<form method="POST" action="" class="form">
    {{ form.hidden_tag() }}
    {% for field in form %}
        {{ render_field(field) }}
    {% endfor %}
    <button type="submit" id="submit">Login!</button>
</form>
{% endblock %}

login.html

Chris Freeman
Chris Freeman
Treehouse Moderator 68,468 Points

This still has quotes around the word content. The quote marks need to be removed.

import datetime

from flask.ext.bcrypt import generate_password_hash
from flask.ext.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',)

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


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

models.py

from flask_wtf import Form
from wtforms import StringField, PasswordField
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()])

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

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


@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('/')
def index():
    return 'Hey'



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

app.py

jinja2.exceptions.TemplateSyntaxError: expected token 'end of print statement', got 'string'

this error has now returned

Thanks Chris but I fixed the problem, and you told me to use the quotes on one of the threads xD. Flask syntax had changed, that was the problem, I had to do a lot of research but it paid off!

Chris Freeman
Chris Freeman
Treehouse Moderator 68,468 Points

Using quotes isn't correct. Can you point out which thread so I can correct it or clarify it?