FlaskFM project

I’m struggling to figure out what I’m doing wrong. I’m at step 17 of the FlaskFm project. I’ve changed the my_playlist part of the code as asked but now I’m getting this error when I’m saving my code:

TypeError: str returned non-string (type NoneType)

I think it has something to do with the Song stuff but I’m not sure. Here’s my code:

routes.py

from flask import Flask
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from app import app, db
from models import User, Song, Playlist, Item
from flask import render_template, request, url_for, redirect, flash

#A form for inputing new songs via Dashboard
class SongForm(FlaskForm):
  title = StringField(label = "Song Title:", validators=[DataRequired()])
  artist = StringField(label = "Artist:", validators=[DataRequired()])
  submit = SubmitField("Add Song")

#A function we made to check if an item to be added is already in the playlist
def exists(item, playlist):
  """Return a boolean
    True if playlist contains item. False otherwise.
    """
  for i in playlist: #for each item in playlist
    if i.song_id == item.song_id: #check if the primary key is equal
       return True
  return False

#The home page of FlaskFM
#Lists all the users currently in the database
#renders the home.html template providing the list of current users
@app.route('/profiles')
def profiles():
    current_users = User.query.all() #change here to a database query
    return render_template('users.html', current_users = current_users)

#Displays profile pages for a user with the user_id primary key
#renders the profile.html template for a specific user, song library and 
#the user's playlist 
@app.route('/profile/<int:user_id>')
def profile(user_id):
   user = User.query.filter_by(id = user_id).first_or_404(description = "No such user found.")
   songs = Song.query.all()
   my_playlist = Playlist.query.get(user.playlist_id) #change here to a database query
   return  render_template('profile.html', user = user, my_playlist = my_playlist, songs = songs)#, my_playlist = my_playlist)

#Adds new songs to a user's playlist from the song library
#redirects back to the profile that issued the addition
@app.route('/add_item/<int:user_id>/<int:song_id>/<int:playlist_id>')
def add_item(user_id, song_id, playlist_id):
   new_item = Item(song_id = song_id, playlist_id = playlist_id)
   user = User.query.filter_by(id = user_id).first_or_404(description = "No such user found.")
   my_playlist = Playlist.query.filter_by(id = user.playlist_id).first()
   if not exists(new_item, my_playlist.items):
      song = Song.query.get(song_id)
      #using db session add the new item
      #increase the counter for the song associated with the new item
      #commit the database changes here
   return redirect(url_for('profile', user_id = user_id))

#Remove an item from a user's playlist
#Redirects back to the profile that issues the removal
@app.route('/remove_item/<int:user_id>/<int:item_id>')
def remove_item(user_id, item_id):
   #from the Item model, fetch the item with primary key item_id to be deleted
   #using db.session delete the item
   #commit the deletion
   return redirect(url_for('profile', user_id = user_id))
   
#Display the Dashboard page with a form for adding songs
#Renders the dashboard template
@app.route('/dashboard', methods=["GET", "POST"])
def dashboard():
  form = SongForm()
  if request.method == 'POST' and form.validate():
    new_song = None
    #create a new song here
    #add it to the database
    #commit to the database
  else:
        flash(form.errors)
  unpopular_songs = []  #add the ordering query here
  songs = Song.query.all()
  return render_template('dashboard.html', songs = songs, unpopular_songs = unpopular_songs, form = form)

models.py

from app import app, db

#the User model: each user has a username, and a playlist_id foreign key referring

#to the user's Playlist

class User(db.Model):

  id = db.Column(db.Integer, primary_key = True)

  username = db.Column(db.String(50), index = True, unique = True) 

  playlist_id = db.Column(db.Integer,  db.ForeignKey('playlist.id'))

  

  #representation method

  def __repr__(self):

        return "{}".format(self.username)

#create the Song model here + add a nice representation method

class Song(db.Model):

  id = db.Column(db.Integer, primary_key = True)

  artist = db.Column(db.String(50), index = True, unique = False)

  title = db.Column(db.String(75), index = True, unique = False)

  n = db.Column(db.Integer, index = False, unique = False)

  def __repr__(self):

    f"{self.title} by {self.artist}"

#create the Item model here + add a nice representation method

class Item(db.Model):

  id = db.Column(db.Integer, primary_key = True)

  song_id = db.Column(db.Integer, db.ForeignKey('song.id'))

  playlist_id = db.Column(db.Integer, db.ForeignKey('playlist.id'))

  def __repr__(self):

        return "{}".format(self.id)

#create the Playlist model here + add a nice representation method

class Playlist(db.Model):

  id = db.Column(db.Integer, primary_key = True)

  items = db.relationship('Item', backref = 'playlist', lazy = 'dynamic', cascade = 'all, delete, delete-orphan')

  def __repr__(self):

        return "{}".format(self.id)

app.py

from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
#set the SQLALCHEMY_DATABASE_URI key
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///song_library.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'you-will-never-guess'
#create an SQLAlchemy object named `db` and bind it to your app
db = SQLAlchemy(app)
#a simple initial greeting
@app.route('/')
@app.route('/index')
def greeting():
    return render_template('greeting.html')

# app name 
@app.errorhandler(404) 
def not_found(e): 
  return render_template("404.html") 

#uncomment the code below here when you are done creating database instance db and models
import routes

Here’s the full error:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 2463, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 2449, in wsgi_app
    response = self.handle_exception(e)
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1866, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 2446, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1951, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1820, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/ccuser/workspace/project-flask-music/routes.py", line 41, in profile
    return  render_template('profile.html', user = user, my_playlist = my_playlist, songs = songs)#, my_playlist = my_playlist)
  File "/usr/local/lib/python3.6/dist-packages/flask/templating.py", line 140, in render_template
    ctx.app,
  File "/usr/local/lib/python3.6/dist-packages/flask/templating.py", line 120, in _render
    rv = template.render(context)
  File "/usr/local/lib/python3.6/dist-packages/jinja2/asyncsupport.py", line 76, in render
    return original_render(self, *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/jinja2/environment.py", line 1008, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/local/lib/python3.6/dist-packages/jinja2/environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/dist-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "/home/ccuser/workspace/project-flask-music/templates/profile.html", line 3, in top-level template code
    {% extends "_base.html" %}
  File "/home/ccuser/workspace/project-flask-music/templates/_base.html", line 12, in top-level template code
    {% block content %}{% endblock %}
  File "/home/ccuser/workspace/project-flask-music/templates/profile.html", line 12, in block "content"
    <p>{{song}} {% if my_playlist %}<a href="{{url_for('add_item', user_id = user.id, song_id = song.id, playlist_id = my_playlist.id)}}">Add</a>{% endif %}</p>
TypeError: __str__ returned non-string (type NoneType)

Thanks

2 Likes

Hello, @loganjensen410794599, and welcome to the Codecademy Forums!

In the models.py file, you have a __repr__ method for the Song model, as follows:

  def __repr__(self):

    f"{self.title} by {self.artist}"

Note that it does not contain a return statement. Revisit instruction 7.

Edited on October 14, 2020 to add the following:

Link to project: FlaskFM

4 Likes

Thanks so much! I knew it had to be something simple I was missing. I appreciate your help with debugging my code!

2 Likes