Added complete console logging for parsing library
Specifically, when making API calls for genres/features and updating genres for tracks in db.
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
# https://stackoverflow.com/a/34576062/8811872
|
sudo -u postgres psql
|
||||||
|
|
||||||
sudo su postgres
|
|
||||||
psql
|
|
||||||
drop database spotifyvis;
|
drop database spotifyvis;
|
||||||
create database spotifyvis with owner django;
|
create database spotifyvis with owner django;
|
||||||
|
|
||||||
\q
|
\q
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ class Artist(models.Model):
|
|||||||
verbose_name_plural = "Artists"
|
verbose_name_plural = "Artists"
|
||||||
|
|
||||||
artist_id = models.CharField(primary_key=True, max_length=MAX_ID)
|
artist_id = models.CharField(primary_key=True, max_length=MAX_ID)
|
||||||
# unique since only storing one genre per artist right now
|
name = models.CharField(max_length=50)
|
||||||
name = models.CharField(unique=True, max_length=50)
|
|
||||||
genres = models.ManyToManyField(Genre, blank=True)
|
genres = models.ManyToManyField(Genre, blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|||||||
@@ -11,12 +11,16 @@ import json
|
|||||||
|
|
||||||
# }}} imports #
|
# }}} imports #
|
||||||
|
|
||||||
|
# API limits {{{ #
|
||||||
|
|
||||||
USER_TRACKS_LIMIT = 50
|
USER_TRACKS_LIMIT = 50
|
||||||
ARTIST_LIMIT = 50
|
ARTIST_LIMIT = 50
|
||||||
FEATURES_LIMIT = 100
|
FEATURES_LIMIT = 100
|
||||||
# ARTIST_LIMIT = 25
|
# ARTIST_LIMIT = 25
|
||||||
# FEATURES_LIMIT = 25
|
# FEATURES_LIMIT = 25
|
||||||
|
|
||||||
|
# }}} API limits #
|
||||||
|
|
||||||
# parse_library {{{ #
|
# parse_library {{{ #
|
||||||
|
|
||||||
def parse_library(headers, tracks, user):
|
def parse_library(headers, tracks, user):
|
||||||
@@ -63,10 +67,8 @@ def parse_library(headers, tracks, user):
|
|||||||
|
|
||||||
# }}} add artists #
|
# }}} add artists #
|
||||||
|
|
||||||
# TODO: fix this, don't need any more
|
|
||||||
top_genre = ""
|
|
||||||
track_obj, track_created = save_track_obj(track_dict['track'],
|
track_obj, track_created = save_track_obj(track_dict['track'],
|
||||||
track_artists, top_genre, user)
|
track_artists, user)
|
||||||
|
|
||||||
# add audio features {{{ #
|
# add audio features {{{ #
|
||||||
|
|
||||||
@@ -80,8 +82,8 @@ def parse_library(headers, tracks, user):
|
|||||||
|
|
||||||
# }}} add audio features #
|
# }}} add audio features #
|
||||||
|
|
||||||
# temporary console logging
|
# console logging
|
||||||
print("#{}-{}: {} - {}".format(offset + 1,
|
print("Added track #{}-{}: {} - {}".format(offset + 1,
|
||||||
offset + USER_TRACKS_LIMIT,
|
offset + USER_TRACKS_LIMIT,
|
||||||
track_obj.artists.first(),
|
track_obj.artists.first(),
|
||||||
track_obj.name))
|
track_obj.name))
|
||||||
@@ -131,13 +133,15 @@ def update_track_genres(user):
|
|||||||
track.genre = most_common_genre if most_common_genre is not None \
|
track.genre = most_common_genre if most_common_genre is not None \
|
||||||
else undefined_genre_obj
|
else undefined_genre_obj
|
||||||
track.save()
|
track.save()
|
||||||
# print(track.name, track.genre)
|
|
||||||
|
# console logging
|
||||||
|
print("Added '{}' as genre for song '{}'".format(track.genre, track.name))
|
||||||
|
|
||||||
# }}} update_track_genres #
|
# }}} update_track_genres #
|
||||||
|
|
||||||
# save_track_obj {{{ #
|
# save_track_obj {{{ #
|
||||||
|
|
||||||
def save_track_obj(track_dict, artists, top_genre, user):
|
def save_track_obj(track_dict, artists, user):
|
||||||
"""Make an entry in the database for this track if it doesn't exist already.
|
"""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.
|
:track_dict: dictionary from the API call containing track information.
|
||||||
@@ -158,7 +162,6 @@ def save_track_obj(track_dict, artists, top_genre, user):
|
|||||||
popularity=int(track_dict['popularity']),
|
popularity=int(track_dict['popularity']),
|
||||||
runtime=int(float(track_dict['duration_ms']) / 1000),
|
runtime=int(float(track_dict['duration_ms']) / 1000),
|
||||||
name=track_dict['name'],
|
name=track_dict['name'],
|
||||||
# genre=top_genre,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# have to add artists and user after saving object since track needs to
|
# have to add artists and user after saving object since track needs to
|
||||||
@@ -200,8 +203,14 @@ def get_audio_features(headers, track_objs):
|
|||||||
setattr(cur_features_obj, key, val)
|
setattr(cur_features_obj, key, val)
|
||||||
cur_features_obj.save()
|
cur_features_obj.save()
|
||||||
|
|
||||||
|
# console logging
|
||||||
|
print("Added features for song #{} - {}".format(i + 1,
|
||||||
|
track_objs[i].name))
|
||||||
|
|
||||||
# }}} get_audio_features #
|
# }}} get_audio_features #
|
||||||
|
|
||||||
|
# process_artist_genre {{{ #
|
||||||
|
|
||||||
def process_artist_genre(genre_name, artist_obj):
|
def process_artist_genre(genre_name, artist_obj):
|
||||||
"""Increase count for correspoding Genre object to genre_name and add that
|
"""Increase count for correspoding Genre object to genre_name and add that
|
||||||
Genre to artist_obj.
|
Genre to artist_obj.
|
||||||
@@ -219,6 +228,8 @@ def process_artist_genre(genre_name, artist_obj):
|
|||||||
artist_obj.genres.add(genre_obj)
|
artist_obj.genres.add(genre_obj)
|
||||||
artist_obj.save()
|
artist_obj.save()
|
||||||
|
|
||||||
|
# }}} process_artist_genre #
|
||||||
|
|
||||||
# add_artist_genres {{{ #
|
# add_artist_genres {{{ #
|
||||||
|
|
||||||
def add_artist_genres(headers, artist_objs):
|
def add_artist_genres(headers, artist_objs):
|
||||||
@@ -236,7 +247,6 @@ def add_artist_genres(headers, artist_objs):
|
|||||||
params = {'ids': artist_ids}
|
params = {'ids': artist_ids}
|
||||||
artists_response = requests.get('https://api.spotify.com/v1/artists/',
|
artists_response = requests.get('https://api.spotify.com/v1/artists/',
|
||||||
headers=headers, params=params).json()['artists']
|
headers=headers, params=params).json()['artists']
|
||||||
# pprint.pprint(artists_response)
|
|
||||||
for i in range(len(artist_objs)):
|
for i in range(len(artist_objs)):
|
||||||
if len(artists_response[i]['genres']) == 0:
|
if len(artists_response[i]['genres']) == 0:
|
||||||
process_artist_genre("undefined", artist_objs[i])
|
process_artist_genre("undefined", artist_objs[i])
|
||||||
@@ -244,6 +254,10 @@ def add_artist_genres(headers, artist_objs):
|
|||||||
for genre in artists_response[i]['genres']:
|
for genre in artists_response[i]['genres']:
|
||||||
process_artist_genre(genre, artist_objs[i])
|
process_artist_genre(genre, artist_objs[i])
|
||||||
|
|
||||||
|
# console logging
|
||||||
|
print("Added genres for artist #{} - {}".format(i + 1,
|
||||||
|
artist_objs[i].name))
|
||||||
|
|
||||||
# }}} add_artist_genres #
|
# }}} add_artist_genres #
|
||||||
|
|
||||||
# get_artists_in_genre {{{ #
|
# get_artists_in_genre {{{ #
|
||||||
|
|||||||
@@ -18,9 +18,13 @@ from .models import User, Track, AudioFeatures, Artist
|
|||||||
|
|
||||||
# }}} imports #
|
# }}} imports #
|
||||||
|
|
||||||
|
# global vars {{{ #
|
||||||
|
|
||||||
TIME_FORMAT = '%Y-%m-%d-%H-%M-%S'
|
TIME_FORMAT = '%Y-%m-%d-%H-%M-%S'
|
||||||
TRACKS_TO_QUERY = 200
|
TRACKS_TO_QUERY = 200
|
||||||
|
|
||||||
|
# }}} global vars #
|
||||||
|
|
||||||
# generate_random_string {{{ #
|
# generate_random_string {{{ #
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +70,8 @@ def index(request):
|
|||||||
|
|
||||||
# uses Authorization Code flow
|
# uses Authorization Code flow
|
||||||
def login(request):
|
def login(request):
|
||||||
# use a randomly generated state string to prevent cross-site request forgery attacks
|
# use a randomly generated state string to prevent cross-site request
|
||||||
|
# forgery attacks
|
||||||
state_str = generate_random_string(16)
|
state_str = generate_random_string(16)
|
||||||
request.session['state_string'] = state_str
|
request.session['state_string'] = state_str
|
||||||
|
|
||||||
@@ -79,7 +84,8 @@ def login(request):
|
|||||||
'show_dialog': False
|
'show_dialog': False
|
||||||
}
|
}
|
||||||
|
|
||||||
params = urllib.parse.urlencode(payload) # turn the payload dict into a query string
|
# turn the payload dict into a query string
|
||||||
|
params = urllib.parse.urlencode(payload)
|
||||||
authorize_url = "https://accounts.spotify.com/authorize/?{}".format(params)
|
authorize_url = "https://accounts.spotify.com/authorize/?{}".format(params)
|
||||||
return redirect(authorize_url)
|
return redirect(authorize_url)
|
||||||
|
|
||||||
@@ -170,8 +176,10 @@ def user_data(request):
|
|||||||
|
|
||||||
# }}} user_data #
|
# }}} user_data #
|
||||||
|
|
||||||
|
# admin_graphs {{{ #
|
||||||
|
|
||||||
def admin_graphs(request):
|
def admin_graphs(request):
|
||||||
"""TODO
|
"""Redirect to logged in page as ourselves. For testing purposes.
|
||||||
"""
|
"""
|
||||||
user_id = "polarbier"
|
user_id = "polarbier"
|
||||||
# user_id = "chrisshyi13"
|
# user_id = "chrisshyi13"
|
||||||
@@ -183,6 +191,8 @@ def admin_graphs(request):
|
|||||||
update_track_genres(user_obj)
|
update_track_genres(user_obj)
|
||||||
return render(request, 'spotifyvis/logged_in.html', context)
|
return render(request, 'spotifyvis/logged_in.html', context)
|
||||||
|
|
||||||
|
# }}} admin_graphs #
|
||||||
|
|
||||||
# get_artist_data {{{ #
|
# get_artist_data {{{ #
|
||||||
|
|
||||||
def get_artist_data(request, user_secret):
|
def get_artist_data(request, user_secret):
|
||||||
@@ -197,6 +207,8 @@ def get_artist_data(request, user_secret):
|
|||||||
|
|
||||||
# }}} get_artist_data #
|
# }}} get_artist_data #
|
||||||
|
|
||||||
|
# display_genre_graph {{{ #
|
||||||
|
|
||||||
def display_genre_graph(request, client_secret):
|
def display_genre_graph(request, client_secret):
|
||||||
user = User.objects.get(user_secret=client_secret)
|
user = User.objects.get(user_secret=client_secret)
|
||||||
context = {
|
context = {
|
||||||
@@ -204,6 +216,10 @@ def display_genre_graph(request, client_secret):
|
|||||||
}
|
}
|
||||||
return render(request, "spotifyvis/genre_graph.html", context)
|
return render(request, "spotifyvis/genre_graph.html", context)
|
||||||
|
|
||||||
|
# }}} display_genre_graph #
|
||||||
|
|
||||||
|
# audio_features graph {{{ #
|
||||||
|
|
||||||
def audio_features(request, client_secret):
|
def audio_features(request, client_secret):
|
||||||
user = User.objects.get(user_secret=client_secret)
|
user = User.objects.get(user_secret=client_secret)
|
||||||
context = {
|
context = {
|
||||||
@@ -212,6 +228,8 @@ def audio_features(request, client_secret):
|
|||||||
}
|
}
|
||||||
return render(request, "spotifyvis/audio_features.html", context)
|
return render(request, "spotifyvis/audio_features.html", context)
|
||||||
|
|
||||||
|
# }}} audio_features graph #
|
||||||
|
|
||||||
# get_audio_feature_data {{{ #
|
# get_audio_feature_data {{{ #
|
||||||
|
|
||||||
def get_audio_feature_data(request, audio_feature, client_secret):
|
def get_audio_feature_data(request, audio_feature, client_secret):
|
||||||
|
|||||||
Reference in New Issue
Block a user