FlaskFM Malformed Disk

I am on step 15 of Flask FM project (https://www.codecademy.com/paths/build-python-web-apps-flask/tracks/flask-sql-databases/modules/flask-sql-alchemy/projects/flask-database-music). I’m still having a lot of trouble getting the database to work as expected. I’ve tried deleting and recreating it, along with resetting the entire workspace and rewriting the code.

Right now I’m getting the error:
sqlalchemy.exc.DatabaseError: (sqlite3.DatabaseError) database disk image is malformed
[SQL: SELECT song.id AS song_id, song.artist AS song_artist, song.title AS song_title, song.n AS song_n
FROM song]
(Background on this error at: http://sqlalche.me/e/4xp6)

app.py

from flask import Flask, render_template
#import SQLALchemy
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
#set the SQLALCHEMY_DATABASE_URI key
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///my_database.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

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(50), index = True, unique = False)
  n = db.Column(db.Integer, index = False, unique = False)
  def __repr__(self):
    return "{} by {}".format(self.title, 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'))

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

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 = [] #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 = None #change here to a database query
   return render_template('profile.html', user = user, 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)

Hi I would suggest starting from a point of deleting your db file my_database.db (you can make a copy if you wish) and re-making from the terminal.

It may be that you changed the models in an incompatible way at one point and tried to force something on the previous version of your db. You should also double check that your models.py is clean.

I tried running this code and it works fine, no problems (though I didn’t test it deeply I did create a db and added some data into it).

2 Likes

I deleted and recreated the DB, ran add_data.py. I got this error again after saving the next step.

sqlalchemy.exc.DatabaseError: (sqlite3.DatabaseError) database disk image is malformed
[SQL: SELECT user.id AS user_id, user.username AS user_username, user.playlist_id AS user_playlist_id 
FROM user]
(Background on this error at: http://sqlalche.me/e/4xp6)

I decided to continue on and just recreate the db for each step, but it started to work reliably around step 17. Not sure what changed. :man_shrugging:

I’m not familiar with the exercise modules for flask.

My recommendation for when you have your own project (if you want to do it with flask) is to set out some time and get familiar with documentation for setting up sqlalchemy with flask and all the different types of configurations. Every time I blindly followed some guide I always ran into trouble with my db’s but once I had more control of the set-up process it was less of a headache.

Of course, you can always just use django and worry less about this aspect. But that’s not always ideal.

2 Likes

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.