From b73588789909110dd6068b603dbc8373e8ac23eb Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Mon, 4 Jun 2018 22:17:31 -0400 Subject: [PATCH 01/12] Bug fixes Server crashes as of the last commit, now fixed. --- .../migrations/0002_auto_20180605_0209.py | 18 ++++++++++++++++++ .../migrations/0003_auto_20180605_0211.py | 18 ++++++++++++++++++ spotifyvis/models.py | 2 +- spotifyvis/templates/spotifyvis/user_data.html | 1 + spotifyvis/views.py | 15 ++++++++++----- 5 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 spotifyvis/migrations/0002_auto_20180605_0209.py create mode 100644 spotifyvis/migrations/0003_auto_20180605_0211.py diff --git a/spotifyvis/migrations/0002_auto_20180605_0209.py b/spotifyvis/migrations/0002_auto_20180605_0209.py new file mode 100644 index 0000000..fe5fb37 --- /dev/null +++ b/spotifyvis/migrations/0002_auto_20180605_0209.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.5 on 2018-06-05 02:09 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('spotifyvis', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='user', + old_name='username', + new_name='user_name', + ), + ] diff --git a/spotifyvis/migrations/0003_auto_20180605_0211.py b/spotifyvis/migrations/0003_auto_20180605_0211.py new file mode 100644 index 0000000..9e59bb3 --- /dev/null +++ b/spotifyvis/migrations/0003_auto_20180605_0211.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.5 on 2018-06-05 02:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('spotifyvis', '0002_auto_20180605_0209'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='user_name', + field=models.CharField(blank=True, max_length=30), + ), + ] diff --git a/spotifyvis/models.py b/spotifyvis/models.py index 773492c..02a081d 100644 --- a/spotifyvis/models.py +++ b/spotifyvis/models.py @@ -21,7 +21,7 @@ class User(models.Model): verbose_name_plural = "Users" user_id = models.CharField(primary_key=True, max_length=30) # the user's Spotify ID - username = models.CharField(max_length=30) # User's Spotify user name, if set + user_name = models.CharField(max_length=30, blank=True) # User's Spotify user name, if set def __str__(self): return self.username diff --git a/spotifyvis/templates/spotifyvis/user_data.html b/spotifyvis/templates/spotifyvis/user_data.html index c008bdd..209350a 100644 --- a/spotifyvis/templates/spotifyvis/user_data.html +++ b/spotifyvis/templates/spotifyvis/user_data.html @@ -1,3 +1,4 @@ +{% load static %} diff --git a/spotifyvis/views.py b/spotifyvis/views.py index bd7a300..9a9fdd1 100644 --- a/spotifyvis/views.py +++ b/spotifyvis/views.py @@ -135,16 +135,21 @@ def user_data(request): user_data_response = requests.get('https://api.spotify.com/v1/me', headers = headers).json() request.session['user_id'] = user_data_response['id'] # store the user_id so it may be used to create model - request.session['user_name'] = user_data_response['display_name'] + display_name = user_data_response['display_name'] + if display_name is not None: + request.session['user_name'] = display_name + else: + request.session['user_name'] = "" user = None # will be set to the current user object later try: user = User.objects.get(user_id=request.session['user_id']) except User.DoesNotExist: user = User.objects.create(user_id=request.session['user_id'], user_name=request.session['user_name']) - # context = { - # 'user_name': user_data_response['display_name'], - # 'id': user_data_response['id'], - # } + + context = { + 'user_name': user_data_response['display_name'], + 'id': user_data_response['id'], + } library_stats = { "audio_features":{}, From 27718743d74af36d9daca6db5c83749ee0e619f3 Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Tue, 5 Jun 2018 19:55:36 -0400 Subject: [PATCH 02/12] Change artists field in Track artists is now a ManyToManyField in Track, which is cleaner than using a unique_together clause in the Meta class. --- spotifyvis/migrations/0001_initial.py | 10 +++------- ...0605_0209.py => 0002_auto_20180605_2347.py} | 8 ++++---- .../migrations/0003_auto_20180605_0211.py | 18 ------------------ spotifyvis/models.py | 9 ++++----- spotifyvis/views.py | 4 +++- 5 files changed, 14 insertions(+), 35 deletions(-) rename spotifyvis/migrations/{0002_auto_20180605_0209.py => 0002_auto_20180605_2347.py} (59%) delete mode 100644 spotifyvis/migrations/0003_auto_20180605_0211.py diff --git a/spotifyvis/migrations/0001_initial.py b/spotifyvis/migrations/0001_initial.py index e22ffd2..18f13b6 100644 --- a/spotifyvis/migrations/0001_initial.py +++ b/spotifyvis/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.0.5 on 2018-06-03 23:01 +# Generated by Django 2.0.5 on 2018-06-05 20:53 from django.db import migrations, models import django.db.models.deletion @@ -43,7 +43,7 @@ class Migration(migrations.Migration): name='User', fields=[ ('user_id', models.CharField(max_length=30, primary_key=True, serialize=False)), - ('username', models.CharField(max_length=30)), + ('user_name', models.CharField(blank=True, max_length=30)), ], options={ 'verbose_name': 'User', @@ -71,15 +71,11 @@ class Migration(migrations.Migration): migrations.AddField( model_name='track', name='artist', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='spotifyvis.Artist'), + field=models.ManyToManyField(to='spotifyvis.Artist'), ), migrations.AddField( model_name='track', name='users', field=models.ManyToManyField(to='spotifyvis.User'), ), - migrations.AlterUniqueTogether( - name='track', - unique_together={('track_id', 'artist')}, - ), ] diff --git a/spotifyvis/migrations/0002_auto_20180605_0209.py b/spotifyvis/migrations/0002_auto_20180605_2347.py similarity index 59% rename from spotifyvis/migrations/0002_auto_20180605_0209.py rename to spotifyvis/migrations/0002_auto_20180605_2347.py index fe5fb37..af053ab 100644 --- a/spotifyvis/migrations/0002_auto_20180605_0209.py +++ b/spotifyvis/migrations/0002_auto_20180605_2347.py @@ -1,4 +1,4 @@ -# Generated by Django 2.0.5 on 2018-06-05 02:09 +# Generated by Django 2.0.5 on 2018-06-05 23:47 from django.db import migrations @@ -11,8 +11,8 @@ class Migration(migrations.Migration): operations = [ migrations.RenameField( - model_name='user', - old_name='username', - new_name='user_name', + model_name='track', + old_name='artist', + new_name='artists', ), ] diff --git a/spotifyvis/migrations/0003_auto_20180605_0211.py b/spotifyvis/migrations/0003_auto_20180605_0211.py deleted file mode 100644 index 9e59bb3..0000000 --- a/spotifyvis/migrations/0003_auto_20180605_0211.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.0.5 on 2018-06-05 02:11 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('spotifyvis', '0002_auto_20180605_0209'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='user_name', - field=models.CharField(blank=True, max_length=30), - ), - ] diff --git a/spotifyvis/models.py b/spotifyvis/models.py index 02a081d..7fc5767 100644 --- a/spotifyvis/models.py +++ b/spotifyvis/models.py @@ -20,11 +20,11 @@ class User(models.Model): verbose_name = "User" verbose_name_plural = "Users" - user_id = models.CharField(primary_key=True, max_length=30) # the user's Spotify ID - user_name = models.CharField(max_length=30, blank=True) # User's Spotify user name, if set + user_id = models.CharField(primary_key=True, max_length=30) # the user's Spotify ID + user_name = models.CharField(max_length=30, blank=True) # User's Spotify user name, if set def __str__(self): - return self.username + return self.user_name class Track(models.Model): @@ -32,10 +32,9 @@ class Track(models.Model): class Meta: verbose_name = "Track" verbose_name_plural = "Tracks" - unique_together = ('track_id', 'artist',) track_id = models.CharField(max_length=30) - artist = models.ForeignKey(Artist, on_delete=models.CASCADE) + artists = models.ManyToManyField(Artist) year = models.PositiveSmallIntegerField() popularity = models.DecimalField(decimal_places=2, max_digits=2) runtime = models.PositiveSmallIntegerField() diff --git a/spotifyvis/views.py b/spotifyvis/views.py index 9a9fdd1..55ee2a3 100644 --- a/spotifyvis/views.py +++ b/spotifyvis/views.py @@ -16,6 +16,7 @@ TRACKS_TO_QUERY = 5 # generate_random_string {{{ # + def generate_random_string(length): """Generates a random string of a certain length @@ -145,7 +146,8 @@ def user_data(request): user = User.objects.get(user_id=request.session['user_id']) except User.DoesNotExist: user = User.objects.create(user_id=request.session['user_id'], user_name=request.session['user_name']) - + user.save() + context = { 'user_name': user_data_response['display_name'], 'id': user_data_response['id'], From b66cf1dd87a3f67874aefe411beceae724f39557 Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Wed, 6 Jun 2018 20:56:40 -0400 Subject: [PATCH 03/12] Delete all migrations and start anew Deleted all migrations and started anew to incorporate changes in models. --- spotifyvis/migrations/0001_initial.py | 26 ++++----- .../migrations/0002_auto_20180605_2347.py | 18 ------- .../migrations/0002_auto_20180606_0523.py | 53 ------------------- .../migrations/0003_auto_20180606_0525.py | 23 -------- 4 files changed, 14 insertions(+), 106 deletions(-) delete mode 100644 spotifyvis/migrations/0002_auto_20180605_2347.py delete mode 100644 spotifyvis/migrations/0002_auto_20180606_0523.py delete mode 100644 spotifyvis/migrations/0003_auto_20180606_0525.py diff --git a/spotifyvis/migrations/0001_initial.py b/spotifyvis/migrations/0001_initial.py index db17f34..fb92c44 100644 --- a/spotifyvis/migrations/0001_initial.py +++ b/spotifyvis/migrations/0001_initial.py @@ -1,3 +1,5 @@ +# Generated by Django 2.0.5 on 2018-06-07 00:52 + from django.db import migrations, models import django.db.models.deletion @@ -18,8 +20,8 @@ class Migration(migrations.Migration): ('genre', models.CharField(max_length=20)), ], options={ - 'verbose_name_plural': 'Artists', 'verbose_name': 'Artist', + 'verbose_name_plural': 'Artists', }, ), migrations.CreateModel( @@ -32,8 +34,8 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=75)), ], options={ - 'verbose_name_plural': 'Tracks', 'verbose_name': 'Track', + 'verbose_name_plural': 'Tracks', }, ), migrations.CreateModel( @@ -42,26 +44,26 @@ class Migration(migrations.Migration): ('user_id', models.CharField(max_length=30, primary_key=True, serialize=False)), ], options={ - 'verbose_name_plural': 'Users', 'verbose_name': 'User', + 'verbose_name_plural': 'Users', }, ), migrations.CreateModel( name='AudioFeatures', fields=[ ('track', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='spotifyvis.Track')), - ('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)), ], options={ - 'verbose_name_plural': 'AudioFeatures', 'verbose_name': 'AudioFeatures', + 'verbose_name_plural': 'AudioFeatures', }, ), migrations.AddField( diff --git a/spotifyvis/migrations/0002_auto_20180605_2347.py b/spotifyvis/migrations/0002_auto_20180605_2347.py deleted file mode 100644 index af053ab..0000000 --- a/spotifyvis/migrations/0002_auto_20180605_2347.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.0.5 on 2018-06-05 23:47 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('spotifyvis', '0001_initial'), - ] - - operations = [ - migrations.RenameField( - model_name='track', - old_name='artist', - new_name='artists', - ), - ] diff --git a/spotifyvis/migrations/0002_auto_20180606_0523.py b/spotifyvis/migrations/0002_auto_20180606_0523.py deleted file mode 100644 index 7aaa661..0000000 --- a/spotifyvis/migrations/0002_auto_20180606_0523.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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 deleted file mode 100644 index b8b50db..0000000 --- a/spotifyvis/migrations/0003_auto_20180606_0525.py +++ /dev/null @@ -1,23 +0,0 @@ -# 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), - ), - ] From 79aedc655d09a0e8badefa1fadb3071174a366eb Mon Sep 17 00:00:00 2001 From: Kevin Mok Date: Thu, 7 Jun 2018 21:48:38 -0400 Subject: [PATCH 04/12] Trying to pass artist data from db to frontend --- .../static/spotifyvis/scripts/test_db.js | 11 ++++++ spotifyvis/templates/spotifyvis/index.html | 1 + spotifyvis/templates/spotifyvis/test_db.html | 27 ++++++++++++++ .../templates/spotifyvis/user_data.html | 2 +- spotifyvis/urls.py | 16 +++++---- spotifyvis/utils.py | 36 +++++++++++++++++++ spotifyvis/views.py | 17 +++++++-- 7 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 spotifyvis/static/spotifyvis/scripts/test_db.js create mode 100644 spotifyvis/templates/spotifyvis/test_db.html diff --git a/spotifyvis/static/spotifyvis/scripts/test_db.js b/spotifyvis/static/spotifyvis/scripts/test_db.js new file mode 100644 index 0000000..6830820 --- /dev/null +++ b/spotifyvis/static/spotifyvis/scripts/test_db.js @@ -0,0 +1,11 @@ +console.log("{{ user_id }}"); +artist_data = JSON.parse('{{ artist_data }}'); +artist_data.forEach(function(d) { + console.log(d.name, d.num_songs); +}); + +d3.json("{% url "get_artist_data" user_id %}", function(error, data) { + data.forEach(function(d) { + console.log(d.name, d.num_songs); + }); +}); diff --git a/spotifyvis/templates/spotifyvis/index.html b/spotifyvis/templates/spotifyvis/index.html index 32d6db9..5964b34 100644 --- a/spotifyvis/templates/spotifyvis/index.html +++ b/spotifyvis/templates/spotifyvis/index.html @@ -20,6 +20,7 @@

This is an example of the Authorization Code flow

Log In (Original) + Test DB
diff --git a/spotifyvis/templates/spotifyvis/test_db.html b/spotifyvis/templates/spotifyvis/test_db.html new file mode 100644 index 0000000..3f7a0d0 --- /dev/null +++ b/spotifyvis/templates/spotifyvis/test_db.html @@ -0,0 +1,27 @@ + + + + + + + + + Test DB Page + + + + + +
    + {% for artist in artist_data %} +
  • {{ artist.name }} - {{ artist.num_songs }}
  • + {% endfor %} +
+
 {% filter force_escape %} {% debug %} {% endfilter %} 
+ + {% load static %} + + + diff --git a/spotifyvis/templates/spotifyvis/user_data.html b/spotifyvis/templates/spotifyvis/user_data.html index f31d42f..15fb14a 100644 --- a/spotifyvis/templates/spotifyvis/user_data.html +++ b/spotifyvis/templates/spotifyvis/user_data.html @@ -20,6 +20,6 @@ {% for genre_name, genre_count in genre_dict.items %}
  • {{ genre_name }} - {{ genre_count }}
  • {% endfor %} - + diff --git a/spotifyvis/urls.py b/spotifyvis/urls.py index 0d5e894..55380bd 100644 --- a/spotifyvis/urls.py +++ b/spotifyvis/urls.py @@ -1,9 +1,13 @@ from django.urls import path, include -from . import views +from django.conf.urls import url + +from .views import * urlpatterns = [ - path('', views.index, name='index'), - path('login', views.login, name='login'), - path('callback', views.callback, name='callback'), - path('user_data', views.user_data, name='user_data'), -] \ No newline at end of file + path('', index, name='index'), + path('login', login, name='login'), + path('callback', callback, name='callback'), + path('user_data', user_data, name='user_data'), + path('test_db', test_db, name='test_db'), + path('user_artists/', get_artist_data, name='get_artist_data'), +] diff --git a/spotifyvis/utils.py b/spotifyvis/utils.py index 8ed1cc6..dc684e3 100644 --- a/spotifyvis/utils.py +++ b/spotifyvis/utils.py @@ -3,7 +3,11 @@ import requests import math import pprint + from .models import Artist, User, Track, AudioFeatures +from django.db.models import Count +from django.http import JsonResponse +from django.core import serializers # }}} imports # @@ -372,3 +376,35 @@ def process_library_stats(library_stats): return processed_library_stats # }}} process_library_stats # + +def get_genre_data(user): + """Return genre data needed to create the graph user. + + :user: User object for which to return the data for. + :returns: List of dicts containing counts for each genre. + + """ + pass + # user_tracks = Track.objects.filter(users__exact=user) + # for track in user_tracks: + # print(track.name) + + +def get_artist_data(user_id): + """Return artist data needed to create the graph for user. + + :user_id: user ID for which to return the data for. + :returns: List of dicts containing counts for each artist. + + """ + # TODO: not actual artists for user + # PICK UP: figure out how to pass data to D3/frontend + print(user_id) + # user = User.objects.get(user_id=user_id) + artist_counts = Artist.objects.annotate(num_songs=Count('track')) + processed_artist_data = [{'name': artist.name, 'num_songs': artist.num_songs} for artist in artist_counts] + # for artist in artist_counts: + # print(artist.name, artist.num_songs) + return JsonResponse(processed_artist_data, safe=False) + # return serializers.serialize('json', processed_artist_data) + # return processed_artist_data diff --git a/spotifyvis/views.py b/spotifyvis/views.py index 65c9a31..fbbe02c 100644 --- a/spotifyvis/views.py +++ b/spotifyvis/views.py @@ -1,7 +1,5 @@ # imports {{{ # -from django.shortcuts import render, redirect -from django.http import HttpResponse, HttpResponseBadRequest import math import random import requests @@ -10,7 +8,11 @@ import urllib import json import pprint from datetime import datetime -from .utils import parse_library, process_library_stats + +from django.shortcuts import render, redirect +from django.http import HttpResponse, HttpResponseBadRequest +from django.db.models import Count +from .utils import parse_library, process_library_stats, get_artist_data from .models import User, Track, AudioFeatures, Artist # }}} imports # @@ -167,3 +169,12 @@ def user_data(request): return render(request, 'spotifyvis/user_data.html', context) # }}} user_data # + +def test_db(request): + user_id = "polarbier" + context = { + 'artist_data': get_artist_data(user_id), + 'user_id': user_id, + } + # get_artist_data(user) + return render(request, 'spotifyvis/test_db.html', context) From 797115e9cb07b7aa9dbfe48f2e750e93fd754ab0 Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Fri, 8 Jun 2018 18:45:16 -0400 Subject: [PATCH 05/12] Clean up utils.py to use database Uses of the original library_stats dictionary in utils.py were either removed or commented out, replaced by the saving of models into the database. --- spotifyvis/models.py | 45 ++++++- .../static/spotifyvis/scripts/test_db.js | 8 +- spotifyvis/templates/spotifyvis/test_db.html | 11 +- spotifyvis/utils.py | 113 +++++++----------- spotifyvis/views.py | 21 +++- 5 files changed, 110 insertions(+), 88 deletions(-) diff --git a/spotifyvis/models.py b/spotifyvis/models.py index 19a99be..aacfd1e 100644 --- a/spotifyvis/models.py +++ b/spotifyvis/models.py @@ -1,8 +1,7 @@ from django.db import models # id's are 22 in length in examples but set to 30 for buffer -id_length=30 - +MAX_ID = 30 # Artist {{{ # class Artist(models.Model): @@ -10,7 +9,7 @@ class Artist(models.Model): verbose_name = "Artist" verbose_name_plural = "Artists" - artist_id = models.CharField(primary_key=True, max_length=id_length) + artist_id = models.CharField(primary_key=True, max_length=MAX_ID) # unique since only storing one genre per artist right now name = models.CharField(unique=True, max_length=50) genre = models.CharField(max_length=20) @@ -27,7 +26,7 @@ class User(models.Model): verbose_name = "User" verbose_name_plural = "Users" - user_id = models.CharField(primary_key=True, max_length=id_length) # the user's Spotify ID + user_id = models.CharField(primary_key=True, max_length=MAX_ID) # the user's Spotify ID # username = models.CharField(max_length=30) # User's Spotify user name, if set def __str__(self): @@ -43,7 +42,7 @@ class Track(models.Model): verbose_name = "Track" verbose_name_plural = "Tracks" - track_id = models.CharField(primary_key=True, max_length=id_length) + track_id = models.CharField(primary_key=True, max_length=MAX_ID) # artist = models.ForeignKey(Artist, on_delete=models.CASCADE) artists = models.ManyToManyField(Artist, blank=True) year = models.PositiveSmallIntegerField() @@ -79,3 +78,39 @@ class AudioFeatures(models.Model): return super(AudioFeatures, self).__str__() # }}} AudioFeatures # + + +''' +class UserAudioSummary(models.Model): + """ + Stores the summary of a user's audio preferences + """ + class Meta: + verbose_name = "AudioFeatures" + verbose_name_plural = "AudioFeatures" + + user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True,) + avg_acousticness = models.DecimalField(decimal_places=3, max_digits=3) + stdev_acousticness = models.DecimalField(decimal_places=3, max_digits=3) + + avg_danceability = models.DecimalField(decimal_places=3, max_digits=3) + stdev_danceability = models.DecimalField(decimal_places=3, max_digits=3) + + avg_energy = models.DecimalField(decimal_places=3, max_digits=3) + stdev_energy = models.DecimalField(decimal_places=3, max_digits=3) + + avg_instrumentalness = models.DecimalField(decimal_places=3, max_digits=3) + stdev_instrumentalness = models.DecimalField(decimal_places=3, max_digits=3) + + avg_loudness = models.DecimalField(decimal_places=3, max_digits=6) + stdev_loudness = models.DecimalField(decimal_places=3, max_digits=6) + + avg_speechiness = models.DecimalField(decimal_places=3, max_digits=3) + stdev_speechiness = models.DecimalField(decimal_places=3, max_digits=3) + + avg_tempo = models.DecimalField(decimal_places=3, max_digits=6) + stdev_tempo = models.DecimalField(decimal_places=3, max_digits=6) + + avg_valence = models.DecimalField(decimal_places=3, max_digits=3) + stdev_valence = models.DecimalField(decimal_places=3, max_digits=3) +''' \ No newline at end of file diff --git a/spotifyvis/static/spotifyvis/scripts/test_db.js b/spotifyvis/static/spotifyvis/scripts/test_db.js index 6830820..cb5fb67 100644 --- a/spotifyvis/static/spotifyvis/scripts/test_db.js +++ b/spotifyvis/static/spotifyvis/scripts/test_db.js @@ -1,10 +1,4 @@ -console.log("{{ user_id }}"); -artist_data = JSON.parse('{{ artist_data }}'); -artist_data.forEach(function(d) { - console.log(d.name, d.num_songs); -}); - -d3.json("{% url "get_artist_data" user_id %}", function(error, data) { +d3.json("{% url "get_artist_data", user_id %}").then(function(error, data) { data.forEach(function(d) { console.log(d.name, d.num_songs); }); diff --git a/spotifyvis/templates/spotifyvis/test_db.html b/spotifyvis/templates/spotifyvis/test_db.html index 3f7a0d0..0c51c81 100644 --- a/spotifyvis/templates/spotifyvis/test_db.html +++ b/spotifyvis/templates/spotifyvis/test_db.html @@ -20,8 +20,13 @@ {% endfor %}
     {% filter force_escape %} {% debug %} {% endfilter %} 
    - - {% load static %} - + + diff --git a/spotifyvis/utils.py b/spotifyvis/utils.py index dc684e3..1d61a9e 100644 --- a/spotifyvis/utils.py +++ b/spotifyvis/utils.py @@ -1,5 +1,4 @@ # imports {{{ # - import requests import math import pprint @@ -8,6 +7,7 @@ from .models import Artist, User, Track, AudioFeatures from django.db.models import Count from django.http import JsonResponse from django.core import serializers +import json # }}} imports # @@ -32,7 +32,6 @@ def parse_library(headers, tracks, library_stats, user): payload = {'limit': str(limit)} # use two separate variables to track, because the average popularity also requires num_samples num_samples = 0 # number of actual track samples - feature_data_points = 0 # number of feature data analyses (some tracks do not have analyses available) # iterate until hit requested num of tracks for _ in range(0, tracks, limit): @@ -43,22 +42,27 @@ def parse_library(headers, tracks, library_stats, user): # TODO: refactor the for loop body into helper function # iterate through each track for track_dict in saved_tracks_response['items']: - num_samples += 1 # update artist info before track so that Track object can reference # Artist object track_artists = [] for artist_dict in track_dict['track']['artists']: - increase_artist_count(headers, artist_dict['name'], - artist_dict['id'], library_stats) - track_artists.append(Artist.objects.get_or_create( + artist_obj, artist_created = Artist.objects.get_or_create( artist_id=artist_dict['id'], name=artist_dict['name'], - )[0]) + ) + + update_artist_genre(headers, artist_obj) + # get_or_create() returns a tuple (obj, created) + track_artists.append(artist_obj) - 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'], track_obj) + track_obj, track_created = save_track_obj(track_dict['track'], track_artists, user) + + # if a new track is not created, the associated audio feature does not need to be created again + if track_created: + save_audio_features(headers, track_dict['track']['id'], track_obj) + """ + TODO: Put this login in another function + # Audio analysis could be empty if not present in Spotify database if len(audio_features_dict) != 0: # Track the number of audio analyses for calculating # audio feature averages and standard deviations on the fly @@ -66,62 +70,55 @@ def parse_library(headers, tracks, library_stats, user): for feature, feature_data in audio_features_dict.items(): update_audio_feature_stats(feature, feature_data, feature_data_points, library_stats) - + """ # calculates num_songs with offset + songs retrieved - library_stats['num_songs'] = offset + len(saved_tracks_response['items']) offset += limit - calculate_genres_from_artists(headers, library_stats) + # calculate_genres_from_artists(headers, library_stats) # pprint.pprint(library_stats) # }}} 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: dictionary from the API call containing track information. :artists: artists of the song, passed in as a list of Artist objects. :user: User object for which this Track is to be associated with. - :returns: The created/retrieved Track object. + :returns: (The created/retrieved Track object, created) """ - 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], - popularity=int(track_dict['popularity']), - runtime=int(float(track_dict['duration_ms']) / 1000), - name=track_dict['name'], - ) - # print("pop/run: ", new_track.popularity, new_track.runtime) - - # have to add artists and user after saving object since track needs to - # have ID before filling in m2m field + new_track, created = Track.objects.get_or_create( + track_id=track_dict['id'], + year=track_dict['album']['release_date'].split('-')[0], + popularity=int(track_dict['popularity']), + runtime=int(float(track_dict['duration_ms']) / 1000), + name=track_dict['name'], + ) + + # have to add artists and user after saving object since track needs to + # have ID before filling in m2m field + if created: for artist in artists: 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] + return new_track, created # }}} save_track_obj # # get_audio_features {{{ # -def get_audio_features(headers, track_id, track): - """Returns the audio features of a soundtrack +def save_audio_features(headers, track_id, track): + """Creates and saves a new AudioFeatures object 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 + track: Track object to associate with the new AudioFeatures object - Returns: - A dictionary with the features as its keys, if audio feature data is missing for the track, - an empty dictionary is returned. """ response = requests.get("https://api.spotify.com/v1/audio-features/{}".format(track_id), headers = headers).json() @@ -141,7 +138,6 @@ def get_audio_features(headers, track_id, track): setattr(audio_features_entry, key, val) audio_features_entry.save() - return features_dict # }}} get_audio_features # @@ -300,30 +296,27 @@ def get_track_info(track_dict, library_stats, sample_size): # }}} get_track_info # -# calculate_genres_from_artists {{{ # +# update_genres_from_artists {{{ # + -def calculate_genres_from_artists(headers, library_stats): - """Tallies up genre counts based on artists in library_stats. +def update_artist_genre(headers, artist_obj): + """Updates the top genre for an artist by querying the Spotify API :headers: For making the API call. - :library_stats: Dictionary containing the data mined from user's Spotify library + :artist_obj: the Artist object whose genre field will be updated :returns: None """ - for artist_entry in library_stats['artists'].values(): - artist_response = requests.get('https://api.spotify.com/v1/artists/' + artist_entry['id'], headers=headers).json() - # increase each genre count by artist count - for genre in artist_response['genres']: - increase_nested_key('genres', genre, library_stats, artist_entry['count']) - - # update genre for artist in database with top genre - Artist.objects.filter(artist_id=artist_entry['id']).update(genre=artist_response['genres'][0]) + artist_response = requests.get('https://api.spotify.com/v1/artists/' + artist_obj.id, headers=headers).json() + # update genre for artist in database with top genre + artist_obj.update(genre=artist_response['genres'][0]) # }}} calculate_genres_from_artists # # process_library_stats {{{ # + def process_library_stats(library_stats): """Processes library_stats into format more suitable for D3 consumption @@ -388,23 +381,3 @@ def get_genre_data(user): # user_tracks = Track.objects.filter(users__exact=user) # for track in user_tracks: # print(track.name) - - -def get_artist_data(user_id): - """Return artist data needed to create the graph for user. - - :user_id: user ID for which to return the data for. - :returns: List of dicts containing counts for each artist. - - """ - # TODO: not actual artists for user - # PICK UP: figure out how to pass data to D3/frontend - print(user_id) - # user = User.objects.get(user_id=user_id) - artist_counts = Artist.objects.annotate(num_songs=Count('track')) - processed_artist_data = [{'name': artist.name, 'num_songs': artist.num_songs} for artist in artist_counts] - # for artist in artist_counts: - # print(artist.name, artist.num_songs) - return JsonResponse(processed_artist_data, safe=False) - # return serializers.serialize('json', processed_artist_data) - # return processed_artist_data diff --git a/spotifyvis/views.py b/spotifyvis/views.py index 3ab4f61..6bf090b 100644 --- a/spotifyvis/views.py +++ b/spotifyvis/views.py @@ -10,9 +10,9 @@ import pprint from datetime import datetime from django.shortcuts import render, redirect -from django.http import HttpResponse, HttpResponseBadRequest +from django.http import HttpResponse, HttpResponseBadRequest, JsonResponse from django.db.models import Count -from .utils import parse_library, process_library_stats, get_artist_data +from .utils import parse_library, process_library_stats from .models import User, Track, AudioFeatures, Artist # }}} imports # @@ -44,6 +44,7 @@ def generate_random_string(length): # token_expired {{{ # + def token_expired(token_obtained_at, valid_for): """Returns True if token expired, False if otherwise @@ -143,6 +144,8 @@ def user_data(request): user_data_response = requests.get('https://api.spotify.com/v1/me', headers = headers).json() request.session['user_id'] = user_data_response['id'] # store the user_id so it may be used to create model # request.session['user_name'] = user_data_response['display_name'] + + # get_or_create() returns a tuple (obj, created) user = User.objects.get_or_create(user_id=user_data_response['id'])[0] context = { @@ -174,8 +177,20 @@ def user_data(request): def test_db(request): user_id = "polarbier" context = { - 'artist_data': get_artist_data(user_id), 'user_id': user_id, } # get_artist_data(user) return render(request, 'spotifyvis/test_db.html', context) + + +def get_artist_data(request, user_id): + + # TODO: not actual artists for user + # PICK UP: figure out how to pass data to D3/frontend + print(user_id) + # user = User.objects.get(user_id=user_id) + artist_counts = Artist.objects.annotate(num_songs=Count('track')) + processed_artist_data = [{'name': artist.name, 'num_songs': artist.num_songs} for artist in artist_counts] + # for artist in artist_counts: + # print(artist.name, artist.num_songs) + return JsonResponse(data=processed_artist_data, safe=False) From 90dbda4336075a297cb6ceb437298077f5d59701 Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Fri, 8 Jun 2018 19:47:51 -0400 Subject: [PATCH 06/12] Removed UserAudioSummary class --- spotifyvis/models.py | 40 +++------------------------------------- spotifyvis/utils.py | 2 +- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/spotifyvis/models.py b/spotifyvis/models.py index aacfd1e..f09c87a 100644 --- a/spotifyvis/models.py +++ b/spotifyvis/models.py @@ -4,6 +4,7 @@ from django.db import models MAX_ID = 30 # Artist {{{ # + class Artist(models.Model): class Meta: verbose_name = "Artist" @@ -58,6 +59,7 @@ class Track(models.Model): # AudioFeatures {{{ # + class AudioFeatures(models.Model): class Meta: @@ -77,40 +79,4 @@ class AudioFeatures(models.Model): def __str__(self): return super(AudioFeatures, self).__str__() -# }}} AudioFeatures # - - -''' -class UserAudioSummary(models.Model): - """ - Stores the summary of a user's audio preferences - """ - class Meta: - verbose_name = "AudioFeatures" - verbose_name_plural = "AudioFeatures" - - user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True,) - avg_acousticness = models.DecimalField(decimal_places=3, max_digits=3) - stdev_acousticness = models.DecimalField(decimal_places=3, max_digits=3) - - avg_danceability = models.DecimalField(decimal_places=3, max_digits=3) - stdev_danceability = models.DecimalField(decimal_places=3, max_digits=3) - - avg_energy = models.DecimalField(decimal_places=3, max_digits=3) - stdev_energy = models.DecimalField(decimal_places=3, max_digits=3) - - avg_instrumentalness = models.DecimalField(decimal_places=3, max_digits=3) - stdev_instrumentalness = models.DecimalField(decimal_places=3, max_digits=3) - - avg_loudness = models.DecimalField(decimal_places=3, max_digits=6) - stdev_loudness = models.DecimalField(decimal_places=3, max_digits=6) - - avg_speechiness = models.DecimalField(decimal_places=3, max_digits=3) - stdev_speechiness = models.DecimalField(decimal_places=3, max_digits=3) - - avg_tempo = models.DecimalField(decimal_places=3, max_digits=6) - stdev_tempo = models.DecimalField(decimal_places=3, max_digits=6) - - avg_valence = models.DecimalField(decimal_places=3, max_digits=3) - stdev_valence = models.DecimalField(decimal_places=3, max_digits=3) -''' \ No newline at end of file +# }}} AudioFeatures # \ No newline at end of file diff --git a/spotifyvis/utils.py b/spotifyvis/utils.py index 1d61a9e..2362c1d 100644 --- a/spotifyvis/utils.py +++ b/spotifyvis/utils.py @@ -61,7 +61,7 @@ def parse_library(headers, tracks, library_stats, user): if track_created: save_audio_features(headers, track_dict['track']['id'], track_obj) """ - TODO: Put this login in another function + TODO: Put this logic in another function # Audio analysis could be empty if not present in Spotify database if len(audio_features_dict) != 0: # Track the number of audio analyses for calculating From 0e69d3d1905ed69f2027514fb692f413f6121518 Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Fri, 8 Jun 2018 19:50:50 -0400 Subject: [PATCH 07/12] Removed test_db.js --- spotifyvis/static/spotifyvis/scripts/test_db.js | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 spotifyvis/static/spotifyvis/scripts/test_db.js diff --git a/spotifyvis/static/spotifyvis/scripts/test_db.js b/spotifyvis/static/spotifyvis/scripts/test_db.js deleted file mode 100644 index cb5fb67..0000000 --- a/spotifyvis/static/spotifyvis/scripts/test_db.js +++ /dev/null @@ -1,5 +0,0 @@ -d3.json("{% url "get_artist_data", user_id %}").then(function(error, data) { - data.forEach(function(d) { - console.log(d.name, d.num_songs); - }); -}); From fd7a031bf2b3b0e9be24e516b8a4745cf088328a Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Fri, 8 Jun 2018 19:58:44 -0400 Subject: [PATCH 08/12] Fix incorrect usage of update() update() is a QuerySet method. To update a single object, use save(). --- spotifyvis/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spotifyvis/utils.py b/spotifyvis/utils.py index 2362c1d..b23b3c0 100644 --- a/spotifyvis/utils.py +++ b/spotifyvis/utils.py @@ -310,7 +310,8 @@ def update_artist_genre(headers, artist_obj): """ artist_response = requests.get('https://api.spotify.com/v1/artists/' + artist_obj.id, headers=headers).json() # update genre for artist in database with top genre - artist_obj.update(genre=artist_response['genres'][0]) + artist_obj.genre = artist_response['genres'][0] + artist_obj.save() # }}} calculate_genres_from_artists # From 92d5d174e814ffbe6513875f29f7ebc63ed24bb5 Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Fri, 8 Jun 2018 20:08:17 -0400 Subject: [PATCH 09/12] Modify maximum field length Artist.genre and Track.name had maximum lengths that were not long enough, now increased. --- .../migrations/0002_auto_20180608_2002.py | 18 ++++++++++++++++++ .../migrations/0003_auto_20180608_2007.py | 18 ++++++++++++++++++ spotifyvis/models.py | 4 ++-- spotifyvis/utils.py | 3 ++- 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 spotifyvis/migrations/0002_auto_20180608_2002.py create mode 100644 spotifyvis/migrations/0003_auto_20180608_2007.py diff --git a/spotifyvis/migrations/0002_auto_20180608_2002.py b/spotifyvis/migrations/0002_auto_20180608_2002.py new file mode 100644 index 0000000..b7e48e7 --- /dev/null +++ b/spotifyvis/migrations/0002_auto_20180608_2002.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.5 on 2018-06-09 00:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('spotifyvis', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='artist', + name='genre', + field=models.CharField(max_length=30), + ), + ] diff --git a/spotifyvis/migrations/0003_auto_20180608_2007.py b/spotifyvis/migrations/0003_auto_20180608_2007.py new file mode 100644 index 0000000..323ca26 --- /dev/null +++ b/spotifyvis/migrations/0003_auto_20180608_2007.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.5 on 2018-06-09 00:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('spotifyvis', '0002_auto_20180608_2002'), + ] + + operations = [ + migrations.AlterField( + model_name='track', + name='name', + field=models.CharField(max_length=150), + ), + ] diff --git a/spotifyvis/models.py b/spotifyvis/models.py index f09c87a..07f73ff 100644 --- a/spotifyvis/models.py +++ b/spotifyvis/models.py @@ -13,7 +13,7 @@ class Artist(models.Model): artist_id = models.CharField(primary_key=True, max_length=MAX_ID) # unique since only storing one genre per artist right now name = models.CharField(unique=True, max_length=50) - genre = models.CharField(max_length=20) + genre = models.CharField(max_length=30) def __str__(self): return self.name @@ -49,7 +49,7 @@ class Track(models.Model): year = models.PositiveSmallIntegerField() popularity = models.PositiveSmallIntegerField() runtime = models.PositiveSmallIntegerField() - name = models.CharField(max_length=75) + name = models.CharField(max_length=150) users = models.ManyToManyField(User, blank=True) def __str__(self): diff --git a/spotifyvis/utils.py b/spotifyvis/utils.py index b23b3c0..40d116d 100644 --- a/spotifyvis/utils.py +++ b/spotifyvis/utils.py @@ -90,6 +90,7 @@ def save_track_obj(track_dict, artists, user): :returns: (The created/retrieved Track object, created) """ + print(track_dict['name']) new_track, created = Track.objects.get_or_create( track_id=track_dict['id'], year=track_dict['album']['release_date'].split('-')[0], @@ -308,7 +309,7 @@ def update_artist_genre(headers, artist_obj): :returns: None """ - artist_response = requests.get('https://api.spotify.com/v1/artists/' + artist_obj.id, headers=headers).json() + artist_response = requests.get('https://api.spotify.com/v1/artists/' + artist_obj.artist_id, headers=headers).json() # update genre for artist in database with top genre artist_obj.genre = artist_response['genres'][0] artist_obj.save() From 53f78853d92eabc660770c7faf1d6c22be823db2 Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Fri, 8 Jun 2018 20:59:27 -0400 Subject: [PATCH 10/12] Delete 0001_initial.py --- spotifyvis/migrations/0001_initial.py | 79 --------------------------- 1 file changed, 79 deletions(-) delete mode 100644 spotifyvis/migrations/0001_initial.py diff --git a/spotifyvis/migrations/0001_initial.py b/spotifyvis/migrations/0001_initial.py deleted file mode 100644 index fb92c44..0000000 --- a/spotifyvis/migrations/0001_initial.py +++ /dev/null @@ -1,79 +0,0 @@ -# Generated by Django 2.0.5 on 2018-06-07 00:52 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='Artist', - fields=[ - ('artist_id', models.CharField(max_length=30, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=50, unique=True)), - ('genre', models.CharField(max_length=20)), - ], - options={ - 'verbose_name': 'Artist', - 'verbose_name_plural': 'Artists', - }, - ), - migrations.CreateModel( - name='Track', - fields=[ - ('track_id', models.CharField(max_length=30, primary_key=True, serialize=False)), - ('year', models.PositiveSmallIntegerField()), - ('popularity', models.PositiveSmallIntegerField()), - ('runtime', models.PositiveSmallIntegerField()), - ('name', models.CharField(max_length=75)), - ], - options={ - 'verbose_name': 'Track', - 'verbose_name_plural': 'Tracks', - }, - ), - migrations.CreateModel( - name='User', - fields=[ - ('user_id', models.CharField(max_length=30, primary_key=True, serialize=False)), - ], - options={ - 'verbose_name': 'User', - 'verbose_name_plural': 'Users', - }, - ), - migrations.CreateModel( - name='AudioFeatures', - fields=[ - ('track', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='spotifyvis.Track')), - ('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)), - ], - options={ - 'verbose_name': 'AudioFeatures', - 'verbose_name_plural': 'AudioFeatures', - }, - ), - migrations.AddField( - model_name='track', - name='artists', - field=models.ManyToManyField(blank=True, to='spotifyvis.Artist'), - ), - migrations.AddField( - model_name='track', - name='users', - field=models.ManyToManyField(blank=True, to='spotifyvis.User'), - ), - ] From d995a1544442854ce8004b44d66c9a867912e1f4 Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Fri, 8 Jun 2018 20:59:34 -0400 Subject: [PATCH 11/12] Delete 0002_auto_20180608_2002.py --- .../migrations/0002_auto_20180608_2002.py | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 spotifyvis/migrations/0002_auto_20180608_2002.py diff --git a/spotifyvis/migrations/0002_auto_20180608_2002.py b/spotifyvis/migrations/0002_auto_20180608_2002.py deleted file mode 100644 index b7e48e7..0000000 --- a/spotifyvis/migrations/0002_auto_20180608_2002.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.0.5 on 2018-06-09 00:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('spotifyvis', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='artist', - name='genre', - field=models.CharField(max_length=30), - ), - ] From ef7933fb6742324882dd5d1b2509f4d8811e982f Mon Sep 17 00:00:00 2001 From: Chris Shyi Date: Fri, 8 Jun 2018 20:59:42 -0400 Subject: [PATCH 12/12] Delete 0003_auto_20180608_2007.py --- .../migrations/0003_auto_20180608_2007.py | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 spotifyvis/migrations/0003_auto_20180608_2007.py diff --git a/spotifyvis/migrations/0003_auto_20180608_2007.py b/spotifyvis/migrations/0003_auto_20180608_2007.py deleted file mode 100644 index 323ca26..0000000 --- a/spotifyvis/migrations/0003_auto_20180608_2007.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.0.5 on 2018-06-09 00:07 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('spotifyvis', '0002_auto_20180608_2002'), - ] - - operations = [ - migrations.AlterField( - model_name='track', - name='name', - field=models.CharField(max_length=150), - ), - ]