Browse Source

Import history into DB from exported CSV (#57)

master
Kevin Mok 6 years ago
parent
commit
920a9ad772
  1. 2
      api/urls.py
  2. 103
      api/views.py
  3. 2
      login/utils.py
  4. 7
      login/views.py

2
api/urls.py

@ -14,4 +14,6 @@ urlpatterns = [
name='get_genre_data'), name='get_genre_data'),
path('audio_features/<str:audio_feature>/<str:user_secret>', path('audio_features/<str:audio_feature>/<str:user_secret>',
get_audio_feature_data, name='get_audio_feature_data'), get_audio_feature_data, name='get_audio_feature_data'),
path('import/history/<upload_id>', import_history, name='import_history'),
] ]

103
api/views.py

@ -6,22 +6,26 @@ import requests
import urllib import urllib
import secrets import secrets
import string import string
import csv
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.http import JsonResponse from django.http import JsonResponse
from django.db.models import Count, Q, Max from django.db.models import Count, Q, Max
from django.core.files import File
from .utils import * from .utils import *
from .models import * from .models import *
from login.models import User from login.models import User
from login.utils import get_user_context from login.utils import get_user_context
from dateutil.parser import parse from dateutil.parser import parse
from pprint import pprint from pprint import pprint
from login.models import HistoryUpload
# }}} imports # # }}} imports #
# constants {{{ # # constants {{{ #
USER_TRACKS_LIMIT = 50 USER_TRACKS_LIMIT = 50
TRACKS_LIMIT = 50
HISTORY_LIMIT = 50 HISTORY_LIMIT = 50
ARTIST_LIMIT = 50 ARTIST_LIMIT = 50
FEATURES_LIMIT = 100 FEATURES_LIMIT = 100
@ -29,6 +33,7 @@ FEATURES_LIMIT = 100
# FEATURES_LIMIT = 25 # FEATURES_LIMIT = 25
TRACKS_TO_QUERY = 100 TRACKS_TO_QUERY = 100
HISTORY_ENDPOINT = 'https://api.spotify.com/v1/me/player/recently-played' HISTORY_ENDPOINT = 'https://api.spotify.com/v1/me/player/recently-played'
TRACKS_ENDPOINT = 'https://api.spotify.com/v1/tracks'
console_logging = True console_logging = True
# console_logging = False # console_logging = False
@ -261,3 +266,101 @@ def get_genre_data(request, user_secret):
return JsonResponse(data=list(genre_counts), safe=False) return JsonResponse(data=list(genre_counts), safe=False)
# }}} get_genre_data # # }}} get_genre_data #
# import_history {{{ #
def import_history(request, upload_id):
"""Import history for the user from the file they uploaded.
:upload_id: ID (PK) of the HistoryUpload entry
:returns: None
"""
headers = ['timestamp', 'track_id']
upload_obj = HistoryUpload.objects.get(id=upload_id)
user_headers = get_user_header(upload_obj.user)
with upload_obj.document.open('r') as f:
csv_reader = csv.reader(f, delimiter=',')
rows_read = 0
history_obj_info_lst = []
artist_genre_queue = []
next(csv_reader)
row = next(csv_reader)
last_row = False
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
history_obj_info_lst.append(history_obj_info)
rows_read += 1
if (rows_read % TRACKS_LIMIT == 0) or last_row:
track_ids_lst = [info['track_id'] for info in history_obj_info_lst]
# print(len(track_ids_lst))
track_ids = ','.join(track_ids_lst)
payload = {'ids': track_ids}
tracks_response = requests.get(TRACKS_ENDPOINT,
headers=user_headers,
params=payload).json()['tracks']
responses_processed = 0
for track_dict in tracks_response:
# add artists {{{ #
# update artist info before track so that Track object can reference
# Artist object
track_artists = []
for artist_dict in track_dict['artists']:
artist_obj, artist_created = Artist.objects.get_or_create(
id=artist_dict['id'],
name=artist_dict['name'],)
# only add/tally up artist genres if new
if artist_created:
artist_genre_queue.append(artist_obj)
if len(artist_genre_queue) == ARTIST_LIMIT:
add_artist_genres(user_headers, artist_genre_queue)
artist_genre_queue = []
track_artists.append(artist_obj)
# }}} add artists #
# don't associate history track with User, not necessarily in their
# library
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]
if console_logging:
print("Processed row #{}: {}".format(
(rows_read - TRACKS_LIMIT) + responses_processed, history_obj,))
responses_processed += 1
history_obj_info_lst = []
if len(artist_genre_queue) > 0:
add_artist_genres(user_headers, artist_genre_queue)
# TODO: update track genres from History relation
# update_track_genres(user_obj)
return redirect('graphs:display_history_table')
# }}} get_history #

2
login/utils.py

@ -1,8 +1,10 @@
import string import string
import random import random
import requests import requests
import secrets
from .models import User from .models import User
from .forms import HistoryUploadForm
def get_user_context(user_obj): def get_user_context(user_obj):
"""Get context for rendering with User's ID and secret. """Get context for rendering with User's ID and secret.

7
login/views.py

@ -3,7 +3,6 @@
import math import math
import os import os
import urllib import urllib
import secrets
import pprint import pprint
from datetime import datetime from datetime import datetime
@ -11,7 +10,6 @@ from django.shortcuts import render, redirect
from django.http import HttpResponseBadRequest from django.http import HttpResponseBadRequest
from .models import * from .models import *
from .utils import * from .utils import *
from .forms import HistoryUploadForm
# }}} imports # # }}} imports #
@ -103,7 +101,8 @@ def upload_history(request):
if request.method == 'POST': if request.method == 'POST':
form = HistoryUploadForm(request.POST, request.FILES) form = HistoryUploadForm(request.POST, request.FILES)
if form.is_valid(): if form.is_valid():
form.save()
return redirect('graphs:display_history_table')
upload_obj = form.save()
# return redirect('graphs:display_history_table')
return redirect('api:import_history', upload_id=upload_obj.id)
return render(request, 'login/scan.html', get_scan_context(request)) return render(request, 'login/scan.html', get_scan_context(request))
Loading…
Cancel
Save