From 62cc6c8ccd6178a764d6a309fee1d2cebcea70f6 Mon Sep 17 00:00:00 2001 From: Kevin Mok Date: Wed, 6 Jun 2018 05:36:00 -0400 Subject: [PATCH] Setup AudioFeatures table --- .../migrations/0002_auto_20180606_0523.py | 53 +++++++++++++++++++ .../migrations/0003_auto_20180606_0525.py | 23 ++++++++ spotifyvis/models.py | 16 +++--- spotifyvis/utils.py | 28 +++++++--- 4 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 spotifyvis/migrations/0002_auto_20180606_0523.py create mode 100644 spotifyvis/migrations/0003_auto_20180606_0525.py diff --git a/spotifyvis/migrations/0002_auto_20180606_0523.py b/spotifyvis/migrations/0002_auto_20180606_0523.py new file mode 100644 index 0000000..7aaa661 --- /dev/null +++ b/spotifyvis/migrations/0002_auto_20180606_0523.py @@ -0,0 +1,53 @@ +# Generated by Django 2.0.5 on 2018-06-06 09:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('spotifyvis', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='audiofeatures', + name='acousticness', + field=models.DecimalField(decimal_places=3, max_digits=3), + ), + migrations.AlterField( + model_name='audiofeatures', + name='danceability', + field=models.DecimalField(decimal_places=3, max_digits=3), + ), + migrations.AlterField( + model_name='audiofeatures', + name='energy', + field=models.DecimalField(decimal_places=3, max_digits=3), + ), + migrations.AlterField( + model_name='audiofeatures', + name='instrumentalness', + field=models.DecimalField(decimal_places=3, max_digits=3), + ), + migrations.AlterField( + model_name='audiofeatures', + name='loudness', + field=models.DecimalField(decimal_places=3, max_digits=3), + ), + migrations.AlterField( + model_name='audiofeatures', + name='speechiness', + field=models.DecimalField(decimal_places=3, max_digits=3), + ), + migrations.AlterField( + model_name='audiofeatures', + name='tempo', + field=models.DecimalField(decimal_places=3, max_digits=3), + ), + migrations.AlterField( + model_name='audiofeatures', + name='valence', + field=models.DecimalField(decimal_places=3, max_digits=3), + ), + ] diff --git a/spotifyvis/migrations/0003_auto_20180606_0525.py b/spotifyvis/migrations/0003_auto_20180606_0525.py new file mode 100644 index 0000000..b8b50db --- /dev/null +++ b/spotifyvis/migrations/0003_auto_20180606_0525.py @@ -0,0 +1,23 @@ +# Generated by Django 2.0.5 on 2018-06-06 09:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('spotifyvis', '0002_auto_20180606_0523'), + ] + + operations = [ + migrations.AlterField( + model_name='audiofeatures', + name='loudness', + field=models.DecimalField(decimal_places=3, max_digits=6), + ), + migrations.AlterField( + model_name='audiofeatures', + name='tempo', + field=models.DecimalField(decimal_places=3, max_digits=6), + ), + ] diff --git a/spotifyvis/models.py b/spotifyvis/models.py index 15fee46..50be45f 100644 --- a/spotifyvis/models.py +++ b/spotifyvis/models.py @@ -67,14 +67,14 @@ class AudioFeatures(models.Model): verbose_name_plural = "AudioFeatures" track = models.OneToOneField(Track, on_delete=models.CASCADE, primary_key=True,) - danceability = models.DecimalField(decimal_places=2, max_digits=2) - energy = models.DecimalField(decimal_places=2, max_digits=2) - loudness = models.DecimalField(decimal_places=2, max_digits=2) - speechiness = models.DecimalField(decimal_places=2, max_digits=2) - acousticness = models.DecimalField(decimal_places=2, max_digits=2) - instrumentalness = models.DecimalField(decimal_places=2, max_digits=2) - valence = models.DecimalField(decimal_places=2, max_digits=2) - tempo = models.DecimalField(decimal_places=2, max_digits=2) + acousticness = models.DecimalField(decimal_places=3, max_digits=3) + danceability = models.DecimalField(decimal_places=3, max_digits=3) + energy = models.DecimalField(decimal_places=3, max_digits=3) + instrumentalness = models.DecimalField(decimal_places=3, max_digits=3) + loudness = models.DecimalField(decimal_places=3, max_digits=6) + speechiness = models.DecimalField(decimal_places=3, max_digits=3) + tempo = models.DecimalField(decimal_places=3, max_digits=6) + valence = models.DecimalField(decimal_places=3, max_digits=3) def __str__(self): return super(AudioFeatures, self).__str__() diff --git a/spotifyvis/utils.py b/spotifyvis/utils.py index cc8ff7c..8ed1cc6 100644 --- a/spotifyvis/utils.py +++ b/spotifyvis/utils.py @@ -51,9 +51,10 @@ def parse_library(headers, tracks, library_stats, user): name=artist_dict['name'], )[0]) - save_track_obj(track_dict['track'], track_artists, user) + track_obj = save_track_obj(track_dict['track'], track_artists, user) get_track_info(track_dict['track'], library_stats, num_samples) - audio_features_dict = get_audio_features(headers, track_dict['track']['id']) + audio_features_dict = get_audio_features(headers, + track_dict['track']['id'], track_obj) if len(audio_features_dict) != 0: # Track the number of audio analyses for calculating # audio feature averages and standard deviations on the fly @@ -70,16 +71,19 @@ def parse_library(headers, tracks, library_stats, user): # }}} parse_library # +# save_track_obj {{{ # + def save_track_obj(track_dict, artists, user): """Make an entry in the database for this track if it doesn't exist already. - :track_dict: TODO + :track_dict: dictionary from the API call containing track information. :artists: artists of the song, passed in as a list of Artist objects. - :user: TODO - :returns: None + :user: User object for which this Track is to be associated with. + :returns: The created/retrieved Track object. """ - if len(Track.objects.filter(track_id__exact=track_dict['id'])) == 0: + track_obj_query = Track.objects.filter(track_id__exact=track_dict['id']) + if len(track_obj_query) == 0: new_track = Track.objects.create( track_id=track_dict['id'], year=track_dict['album']['release_date'].split('-')[0], @@ -95,15 +99,21 @@ def save_track_obj(track_dict, artists, user): new_track.artists.add(artist) new_track.users.add(user) new_track.save() + return new_track + elif len(track_obj_query) == 1: + return track_obj_query[0] + +# }}} save_track_obj # # get_audio_features {{{ # -def get_audio_features(headers, track_id): +def get_audio_features(headers, track_id, track): """Returns the audio features of a soundtrack Args: headers: headers containing the API token track_id: the id of the soundtrack, needed to query the Spotify API + track: Track object to associate with the AudioFeatures object Returns: A dictionary with the features as its keys, if audio feature data is missing for the track, @@ -119,9 +129,13 @@ def get_audio_features(headers, track_id): useless_keys = [ "key", "mode", "type", "liveness", "id", "uri", "track_href", "analysis_url", "time_signature", ] + audio_features_entry = AudioFeatures() + audio_features_entry.track = track for key, val in response.items(): if key not in useless_keys: features_dict[key] = val + setattr(audio_features_entry, key, val) + audio_features_entry.save() return features_dict