Python, django, django-Crontab, Spotipy, Spotify API
- Python 3.7.3
- django 3.0.3
- django-crontab 0.7.1
- spotipy 2.12.0
- homepage css style credits to : W3.CSS Templates
- Table css credits to : DataTables
Project Description
This web application manage two Spotify playlists with Spotify's API, songs in collaborative playlist would be delete on a weekly basis from the collaborative playlist and move to another private playlist which serves as an archive. During the process, additional information for each song is fetched from the API and update to the website's database.
Project Highlights
- Using Spotipy to retrieve data from Spotify via django-crontab
- Letting cronjob/django-crontab pass Spotipy's authentication flow
- Calling django's management function with django-crontab
It's possible to use prompt_for_user_token method in the spotipy.util module in your cronjob for authenticating Spotipy, you just need a cached token. Follow the guide at: https://benwiz.io/blog/create-spotify-refresh-token/ of how to generate a token. If you have runned Spotipy somewhere else and managed to get pass the authentication flow once, there would be a cached token named .cached-your_user_id under the same directory.
Name the token .cached-your_user_id or simply copy the existing token, put it in the same directory of your cronjob. Now, whenever you call prompt_for_user_token, the script would simply refresh the token instead of requiring to input a redirect URI.
In cron.py:
from django.core.management import call_command
def your_command():
call_command('your_custom_command', verbosity=0, interactive=False)
return
In settings.py:
CRONJOBS = [
('0 0 * * 1', 'your_project.cron.your_command', '>>' + os.path.join(BASE_DIR, 'cronjob.log')),
]
# Redirect CRONJOBS' output to stdout and stderr
CRONTAB_COMMAND_SUFFIX = '2>&1'
Adding CRONTAB_COMMAND_SUFFIX = '2>&1' would redirect CRONJOBS' output to stdout and stderr, thus allow you to write output to file, very useful.
To avoid TypeError: Unknown option(s) for your_custom_command, you would want to add a stealth_options tuple to your Command class. In my case, that is:
class Command(BaseCommand):
stealth_options = ("interactive",)