From 3d0acc7a4b3c55a91fd67be8f395d74da3de457a Mon Sep 17 00:00:00 2001 From: Kevin Mok Date: Thu, 8 Nov 2018 09:39:10 -0500 Subject: [PATCH] Refactor saving History obj From import_history and parse_history. Also refactor getting CSV information from import_history. --- api/utils.py | 51 ++++++++++++++++++++++- api/views.py | 48 +++++++-------------- graphs/templates/graphs/user_history.html | 1 + graphs/views.py | 1 + 4 files changed, 65 insertions(+), 36 deletions(-) diff --git a/api/utils.py b/api/utils.py index 0f8ec8b..c97b7d4 100644 --- a/api/utils.py +++ b/api/utils.py @@ -236,12 +236,14 @@ def get_artists_in_genre(user, genre, max_songs): # }}} get_artists_in_genre # +# save_track_artists {{{ # + def save_track_artists(track_dict, artist_genre_queue, user_headers): """ Update artist info before creating Track so that Track object can reference Artist object. - :track_dict: TODO - :returns: None + :track_dict: response from Spotify API for track + :returns: list of Artist objects in Track """ track_artists = [] @@ -259,6 +261,10 @@ def save_track_artists(track_dict, artist_genre_queue, user_headers): return track_artists +# }}} save_track_artists # + +# get_user_header {{{ # + def get_user_header(user_obj): """Returns the authorization string needed to make an API call. @@ -284,3 +290,44 @@ def get_user_header(user_obj): user_obj.save() return {'Authorization': "Bearer " + user_obj.access_token} + +# }}} get_user_header # + +def save_history_obj (user, timestamp, track): + """Return (get/create) a History object with the specified parameters. Can't + use built-in get_or_create since don't know auto PK. + + :user: User object History should be associated with + :timestamp: time at which song was listened to + :track: Track object for song + :returns: History object + + """ + history_query = History.objects.filter(user__exact=user, + timestamp__exact=timestamp) + if len(history_query) == 0: + history_obj = History.objects.create(user=user, timestamp=timestamp, + track=track) + else: + history_obj = history_query[0] + + return history_obj + +def get_next_history_row(csv_reader, headers, prev_info): + """Return formatted information from next row in history CSV file. + + :csv_reader: TODO + :headers: + :prev_info: history_obj_info of last row in case no more rows + :returns: (boolean of if last row, dict with information of next row) + + """ + try: + row = next(csv_reader) + # if Track.objects.filter(id__exact=row[1]).exists(): + history_obj_info = {} + for i in range(len(headers)): + history_obj_info[headers[i]] = row[i] + return False, history_obj_info + except StopIteration: + return True, prev_info diff --git a/api/views.py b/api/views.py index a304ebb..a792124 100644 --- a/api/views.py +++ b/api/views.py @@ -150,10 +150,8 @@ def parse_history(request, user_secret): user_headers) track_obj, track_created = save_track_obj(track_dict['track'], track_artists, None) - history_obj, history_created = History.objects.get_or_create( - user=user_obj, - timestamp=parse(track_dict['played_at']), - track=track_obj,) + history_obj = save_history_obj(user_obj, parse(track_dict['played_at']), + track_obj) if console_logging: tracks_processed += 1 @@ -257,19 +255,12 @@ def import_history(request, upload_id): history_obj_info_lst = [] artist_genre_queue = [] - next(csv_reader) - row = next(csv_reader) - last_row = False + # skip header row + last_row, history_obj_info = get_next_history_row(csv_reader, headers, + {}) while not last_row: - - # if Track.objects.filter(id__exact=row[1]).exists(): - history_obj_info = {} - for i in range(len(headers)): - history_obj_info[headers[i]] = row[i] - try: - row = next(csv_reader) - except StopIteration: - last_row = True + last_row, history_obj_info = get_next_history_row(csv_reader, + headers, history_obj_info) # }}} setup # @@ -290,33 +281,22 @@ def import_history(request, upload_id): # }}} get tracks_response # for track_dict in tracks_response: - # create History obj {{{ # - # don't associate history track with User, not necessarily in their # library track_artists = save_track_artists(track_dict, artist_genre_queue, user_headers) - track_obj, track_created = save_track_obj(track_dict, track_artists, None) - - timestamp = parse(history_obj_info_lst[responses_processed]['timestamp']) - # missing PK to do get_or_create - history_query = \ - History.objects.filter(user__exact=upload_obj.user, - timestamp__exact=timestamp) - if len(history_query) == 0: - history_obj = \ - History.objects.create(user=upload_obj.user, - timestamp=timestamp, - track=track_obj,) - else: - history_obj = history_query[0] + track_obj, track_created = save_track_obj(track_dict, + track_artists, None) + + timestamp = \ + parse(history_obj_info_lst[responses_processed]['timestamp']) + history_obj = save_history_obj(upload_obj.user, timestamp, + track_obj) if console_logging: print("Processed row #{}: {}".format( (rows_read - TRACKS_LIMIT) + responses_processed, history_obj,)) responses_processed += 1 - - # }}} create History obj # history_obj_info_lst = [] diff --git a/graphs/templates/graphs/user_history.html b/graphs/templates/graphs/user_history.html index 39c2e27..a7cc84b 100644 --- a/graphs/templates/graphs/user_history.html +++ b/graphs/templates/graphs/user_history.html @@ -10,6 +10,7 @@

{{ user_id }}'s Listening History

+

Found {{ total_history }} songs.

Export {% render_table user_history_table %} diff --git a/graphs/views.py b/graphs/views.py index 404eaac..2c09239 100644 --- a/graphs/views.py +++ b/graphs/views.py @@ -65,6 +65,7 @@ class HistoryList(ExportMixin, SingleTableView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['user_id'] = self.request.session['user_id'] + context['total_history'] = self.get_table_data().count() return context def get_export_filename(self, export_format):