Browse Source

Store counts for genres in Genre model

Have not assigned most common genre to Track models yet (currently
blank).
master
Kevin Mok 7 years ago
parent
commit
de93bd7b0a
  1. 8
      recreate-db.txt
  2. 2
      requirements.txt
  3. 17
      spotifyvis/models.py
  4. 35
      spotifyvis/utils.py

8
recreate-db.txt

@ -0,0 +1,8 @@
# https://stackoverflow.com/a/34576062/8811872
sudo su postgres
psql
drop database spotifyvis;
create database spotifyvis with owner django;
\q
exit

2
requirements.txt

@ -7,7 +7,7 @@ idna==2.6
isort==4.3.4 isort==4.3.4
lazy-object-proxy==1.3.1 lazy-object-proxy==1.3.1
mccabe==0.6.1 mccabe==0.6.1
psycopg2==2.7.4
psycopg2-binary==2.7.4
pylint==1.8.4 pylint==1.8.4
pytz==2018.4 pytz==2018.4
requests==2.18.4 requests==2.18.4

17
spotifyvis/models.py

@ -35,6 +35,18 @@ class User(models.Model):
# }}} User # # }}} User #
class Genre(models.Model):
class Meta:
verbose_name = "Genre"
verbose_name_plural = "Genres"
name = models.CharField(primary_key=True, max_length=50)
num_songs = models.PositiveIntegerField()
def __str__(self):
return self.name
# Track {{{ # # Track {{{ #
class Track(models.Model): class Track(models.Model):
@ -51,7 +63,9 @@ class Track(models.Model):
runtime = models.PositiveSmallIntegerField() runtime = models.PositiveSmallIntegerField()
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
users = models.ManyToManyField(User, blank=True) users = models.ManyToManyField(User, blank=True)
genre = models.CharField(max_length=30)
# genre = models.CharField(max_length=30)
genre = models.ForeignKey(Genre, on_delete=models.CASCADE, blank=True,
null=True)
def __str__(self): def __str__(self):
return self.name return self.name
@ -60,7 +74,6 @@ class Track(models.Model):
# AudioFeatures {{{ # # AudioFeatures {{{ #
class AudioFeatures(models.Model): class AudioFeatures(models.Model):
class Meta: class Meta:

35
spotifyvis/utils.py

@ -3,8 +3,8 @@ import requests
import math import math
import pprint import pprint
from .models import Artist, User, Track, AudioFeatures
from django.db.models import Count, Q
from .models import *
from django.db.models import Count, Q, F
from django.http import JsonResponse from django.http import JsonResponse
from django.core import serializers from django.core import serializers
import json import json
@ -13,7 +13,6 @@ import json
# parse_library {{{ # # parse_library {{{ #
def parse_library(headers, tracks, user): def parse_library(headers, tracks, user):
"""Scans user's library for certain number of tracks to update library_stats with. """Scans user's library for certain number of tracks to update library_stats with.
@ -48,6 +47,8 @@ def parse_library(headers, tracks, user):
artist_id=artist_dict['id'], artist_id=artist_dict['id'],
name=artist_dict['name'], name=artist_dict['name'],
) )
if artist_created:
tally_artist_genres(headers, artist_dict['id'])
# 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)
@ -59,8 +60,8 @@ def parse_library(headers, tracks, user):
track_artists, top_genre, user) track_artists, top_genre, user)
# if a new track is not created, the associated audio feature does not need to be created again # 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)
# if track_created:
save_audio_features(headers, track_dict['track']['id'], track_obj)
""" """
TODO: Put this logic in another function TODO: Put this logic in another function
# Audio analysis could be empty if not present in Spotify database # Audio analysis could be empty if not present in Spotify database
@ -100,7 +101,7 @@ 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,
# 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
@ -126,6 +127,8 @@ def save_audio_features(headers, track_id, track):
""" """
response = requests.get("https://api.spotify.com/v1/audio-features/{}".format(track_id), headers = headers).json() response = requests.get("https://api.spotify.com/v1/audio-features/{}".format(track_id), headers = headers).json()
if track_id is '5S1IUPueD0xE0vj4zU3nSf':
pprint.pprint(response)
if 'error' in response: if 'error' in response:
return return
@ -330,6 +333,7 @@ def get_top_genre(headers, top_artist_id):
""" """
artist_response = requests.get('https://api.spotify.com/v1/artists/' + artist_response = requests.get('https://api.spotify.com/v1/artists/' +
top_artist_id, headers=headers).json() top_artist_id, headers=headers).json()
# pprint.pprint(artist_response)
if len(artist_response['genres']) > 0: if len(artist_response['genres']) > 0:
return artist_response['genres'][0] return artist_response['genres'][0]
else: else:
@ -337,6 +341,25 @@ def get_top_genre(headers, top_artist_id):
# }}} # # }}} #
def tally_artist_genres(headers, artist_id):
"""Tallies up genres for artist for the respective Genre models. Should be
called when new Artist object is created.
:headers: For making the API call.
:artist_id: Artist ID for which to tally up genres for.
:returns: None
"""
artist_response = requests.get('https://api.spotify.com/v1/artists/' +
artist_id, headers=headers).json()
for genre in artist_response['genres']:
genre_obj, created = Genre.objects.get_or_create(name=genre,
defaults={'num_songs':1})
if not created:
genre_obj.num_songs = F('num_songs') +1
genre_obj.save()
# process_library_stats {{{ # # process_library_stats {{{ #
def process_library_stats(library_stats): def process_library_stats(library_stats):

Loading…
Cancel
Save