Use "several" API call to get artist genres
This commit is contained in:
@@ -11,6 +11,11 @@ import json
|
|||||||
|
|
||||||
# }}} imports #
|
# }}} imports #
|
||||||
|
|
||||||
|
USER_TRACKS_LIMIT = 50
|
||||||
|
# ARTIST_LIMIT = 50
|
||||||
|
ARTIST_LIMIT = 25
|
||||||
|
FEATURES_LIMIT = 100
|
||||||
|
|
||||||
# parse_library {{{ #
|
# parse_library {{{ #
|
||||||
|
|
||||||
def parse_library(headers, tracks, user):
|
def parse_library(headers, tracks, user):
|
||||||
@@ -24,14 +29,13 @@ def parse_library(headers, tracks, user):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
# TODO: implement importing entire library with 0 as tracks param
|
# TODO: implement importing entire library with 0 as tracks param
|
||||||
# number of tracks to get with each call
|
|
||||||
limit = 50
|
|
||||||
# keeps track of point to get songs from
|
# keeps track of point to get songs from
|
||||||
offset = 0
|
offset = 0
|
||||||
payload = {'limit': str(limit)}
|
payload = {'limit': str(USER_TRACKS_LIMIT)}
|
||||||
|
artist_genre_queue = []
|
||||||
|
|
||||||
# iterate until hit requested num of tracks
|
# iterate until hit requested num of tracks
|
||||||
for _ in range(0, tracks, limit):
|
for _ in range(0, tracks, USER_TRACKS_LIMIT):
|
||||||
payload['offset'] = str(offset)
|
payload['offset'] = str(offset)
|
||||||
# get current set of tracks
|
# get current set of tracks
|
||||||
saved_tracks_response = requests.get('https://api.spotify.com/v1/me/tracks', headers=headers, params=payload).json()
|
saved_tracks_response = requests.get('https://api.spotify.com/v1/me/tracks', headers=headers, params=payload).json()
|
||||||
@@ -48,14 +52,18 @@ def parse_library(headers, tracks, user):
|
|||||||
name=artist_dict['name'],
|
name=artist_dict['name'],
|
||||||
)
|
)
|
||||||
if artist_created:
|
if artist_created:
|
||||||
add_artist_genres(headers, artist_obj)
|
artist_genre_queue.append(artist_obj)
|
||||||
|
if len(artist_genre_queue) == ARTIST_LIMIT:
|
||||||
|
add_artist_genres(headers, artist_genre_queue)
|
||||||
|
artist_genre_queue = []
|
||||||
|
|
||||||
# update_artist_genre(headers, artist_obj)
|
# update_artist_genre(headers, artist_obj)
|
||||||
# get_or_create() returns a tuple (obj, created)
|
# get_or_create() returns a tuple (obj, created)
|
||||||
track_artists.append(artist_obj)
|
track_artists.append(artist_obj)
|
||||||
|
|
||||||
top_genre = get_top_genre(headers,
|
# top_genre = get_top_genre(headers,
|
||||||
track_dict['track']['artists'][0]['id'])
|
# track_dict['track']['artists'][0]['id'])
|
||||||
|
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, top_genre, user)
|
||||||
|
|
||||||
@@ -74,8 +82,12 @@ def parse_library(headers, tracks, user):
|
|||||||
feature_data_points, library_stats)
|
feature_data_points, library_stats)
|
||||||
"""
|
"""
|
||||||
# calculates num_songs with offset + songs retrieved
|
# calculates num_songs with offset + songs retrieved
|
||||||
offset += limit
|
offset += USER_TRACKS_LIMIT
|
||||||
# pprint.pprint(library_stats)
|
# pprint.pprint(library_stats)
|
||||||
|
|
||||||
|
# update artists left in queue since there will be probably be leftover
|
||||||
|
# artists that didn't hit ARTIST_LIMIT
|
||||||
|
add_artist_genres(headers, artist_genre_queue)
|
||||||
update_track_genres(user)
|
update_track_genres(user)
|
||||||
|
|
||||||
# }}} parse_library #
|
# }}} parse_library #
|
||||||
@@ -359,30 +371,31 @@ def get_top_genre(headers, top_artist_id):
|
|||||||
|
|
||||||
# }}} #
|
# }}} #
|
||||||
|
|
||||||
# add_artist_genres {{{ #
|
def add_artist_genres(headers, artist_objs):
|
||||||
|
"""Adds genres to artist_objs and increases the count the respective Genre
|
||||||
def add_artist_genres(headers, artist_obj):
|
object. artist_objs should contain the API limit for a single call
|
||||||
"""Adds genres to artist_obj and increases the count the respective Genre
|
(ARTIST_LIMIT) for maximum efficiency.
|
||||||
object. Should be called when a new Artist object is created.
|
|
||||||
|
|
||||||
:headers: For making the API call.
|
:headers: For making the API call.
|
||||||
:artist_obj: Artist object for which to add/tally up genres for.
|
:artist_objs: List of Artist objects for which to add/tally up genres for.
|
||||||
|
|
||||||
:returns: None
|
:returns: None
|
||||||
|
|
||||||
"""
|
"""
|
||||||
artist_response = requests.get('https://api.spotify.com/v1/artists/' +
|
artist_ids = str.join(",", [artist_obj.artist_id for artist_obj in artist_objs])
|
||||||
artist_obj.artist_id, headers=headers).json()
|
# print(len(artist_objs), artist_ids)
|
||||||
for genre in artist_response['genres']:
|
params = {'ids': artist_ids}
|
||||||
genre_obj, created = Genre.objects.get_or_create(name=genre,
|
artists_response = requests.get('https://api.spotify.com/v1/artists/',
|
||||||
defaults={'num_songs':1})
|
headers=headers, params=params).json()['artists']
|
||||||
if not created:
|
for i in range(len(artist_objs)):
|
||||||
genre_obj.num_songs = F('num_songs') +1
|
for genre in artists_response[i]['genres']:
|
||||||
genre_obj.save()
|
genre_obj, created = Genre.objects.get_or_create(name=genre,
|
||||||
artist_obj.genres.add(genre_obj)
|
defaults={'num_songs':1})
|
||||||
artist_obj.save()
|
if not created:
|
||||||
|
genre_obj.num_songs = F('num_songs') +1
|
||||||
# }}} add_artist_genres #
|
genre_obj.save()
|
||||||
|
artist_objs[i].genres.add(genre_obj)
|
||||||
|
artist_objs[i].save()
|
||||||
|
|
||||||
# process_library_stats {{{ #
|
# process_library_stats {{{ #
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from .models import User, Track, AudioFeatures, Artist
|
|||||||
# }}} imports #
|
# }}} imports #
|
||||||
|
|
||||||
TIME_FORMAT = '%Y-%m-%d-%H-%M-%S'
|
TIME_FORMAT = '%Y-%m-%d-%H-%M-%S'
|
||||||
TRACKS_TO_QUERY = 100
|
TRACKS_TO_QUERY = 50
|
||||||
|
|
||||||
# generate_random_string {{{ #
|
# generate_random_string {{{ #
|
||||||
|
|
||||||
@@ -65,8 +65,8 @@ def index(request):
|
|||||||
|
|
||||||
# login {{{ #
|
# login {{{ #
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|||||||
Reference in New Issue
Block a user