Restructure relationship b/w Songs and Archives

Songs now have a ForeignKey to Archive - one song can not be part of
many Archives.
master
Bradlee Speice 2013-02-12 15:02:08 -05:00
parent 0d467e8457
commit 17960be548
2 changed files with 23 additions and 15 deletions

View File

@ -1,7 +1,5 @@
from django.db import models
from song import Song
"""
This is the archive model for the archiving backend of Melodia.
It's purpose is to control the high-level functionality of managing
@ -31,8 +29,8 @@ class Archive (models.Model):
#Note that we're not using FilePathField since this is actually a folder
root_folder = models.CharField(max_length = 255)
#And a reference to the songs in this archive
songs = models.ManyToManyField(Song)
#We've removed the reference to "songs" - instead define it as a ForeignKey,
#and do lookups via song_set
#Backup settings
backup_location = models.CharField(max_length = 255, default = "/dev/null")
@ -53,7 +51,7 @@ class Archive (models.Model):
#It's hackish, but far fewer transactions to delete everything first, and add it all back.
#If we get interrupted, just re-run it.
self.songs.all().delete()
song_set.all().delete()
#Add new songs
for dirname, dirnames, filenames in os.walk(self.root_folder):
@ -63,16 +61,16 @@ class Archive (models.Model):
full_url = os.path.abspath(rel_url)
new_song = Song(url = full_url)
new_song.save()
self.songs.add(new_song)
song_set.add(new_song)
def _update_song_metadata(self, use_echonest = False, progress_callback = lambda x, y: None):
"""Scan every song in this archive (database only) and make sure all songs are correct
The progress_callback function is called with the current song being operated on first, and the total songs second."""
#This method operates only on the songs that are in the database - if you need to make
#sure that new songs are added, use the _scan_filesystem() method in addition
total_songs = self.songs.count()
total_songs = song_set.count()
for index, song in enumerate(self.songs.all()):
for index, song in enumerate(song_set.all()):
song.populate_metadata(use_echonest = use_echonest)
song.save()
progress_callback(index + 1, total_songs)
@ -133,9 +131,9 @@ class Archive (models.Model):
"""
import os, shutil, errno
total_songs = self.songs.count()
total_songs = song_set.count()
for index, song in enumerate(self.songs.all()):
for index, song in enumerate(song_set.all()):
_current_filename = os.path.basename(song.url)
_current_filename_no_extension = os.path.splitext(_current_filename)[0]

View File

@ -1,7 +1,10 @@
from django.db import models
from Melodia import melodia_settings
from archive import Archive
import datetime
import os.path
"""
The Song model
Each instance of a Song represents a single music file.
@ -63,6 +66,9 @@ class Song (models.Model):
skip_count = models.IntegerField(default = _default_int)
rating = models.IntegerField(default = _default_int, choices = _default_rating_choices)
#Link back to the archive this comes from
parent_archive = models.ForeignKey(Archive)
#Set a static reference to the rating options
RATING_DEFAULT = _default_rating
RATING_BAD = _default_rating_bad
@ -71,6 +77,10 @@ class Song (models.Model):
RATING_GOOD = _default_rating_good
RATING_EXCELLENT = _default_rating_excellent
def _get_full_url(self):
"Combine this song's URL with the URL of its parent"
return os.path.join(parent_archive.root_folder, self.url)
def _file_not_changed(self):
"Make sure the hash for this file is valid - return True if it has not changed."
#Overload the hash function with whatever Melodia as a whole is using
@ -79,7 +89,7 @@ class Song (models.Model):
#Check if there's a hash entry - if there is, the song may not have changed,
#and we can go ahead and return
if self.file_hash != None:
song_file = open(self.url, 'rb')
song_file = open(self._get_full_url, 'rb')
current_file_hash = hash(song_file.read())
if current_file_hash == self.file_hash:
@ -94,10 +104,10 @@ class Song (models.Model):
#Overload the hash function with whatever Melodia as a whole is using
from Melodia.melodia_settings import HASH_FUNCTION as hash
file_handle = open(self.url, 'rb')
file_handle = open(self._get_full_url, 'rb')
self.file_hash = hash(file_handle.read())
self.file_size = os.stat(self.url).st_size
self.file_size = os.stat(self._get_full_url).st_size
def _grab_metadata_echonest(self):
"Populate this song's metadata using EchoNest"
@ -110,8 +120,8 @@ class Song (models.Model):
try:
#Use mutagen to scan local metadata - don't update anything else (i.e. play_count)
track = mutagen.File(self.url)
track_easy = mutagen.File(self.url, easy=True)
track = mutagen.File(self._get_full_url)
track_easy = mutagen.File(self._get_full_url, easy=True)
self.title = track_easy['title'][0] or _default_string
self.artist = track_easy['artist'][0] or _default_string