diff --git a/savepointradio/profiles/__init__.py b/savepointradio/profiles/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/savepointradio/profiles/admin.py b/savepointradio/profiles/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/savepointradio/profiles/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/savepointradio/profiles/apps.py b/savepointradio/profiles/apps.py new file mode 100644 index 0000000..5501fda --- /dev/null +++ b/savepointradio/profiles/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ProfilesConfig(AppConfig): + name = 'profiles' diff --git a/savepointradio/profiles/managers.py b/savepointradio/profiles/managers.py new file mode 100644 index 0000000..2a3593b --- /dev/null +++ b/savepointradio/profiles/managers.py @@ -0,0 +1,13 @@ +from django.db import models + + +class RequestManager(models.Manager): + def get_queryset(self): + return super().get_queryset() + + def unplayed(self): + return self.get_queryset().filter(queued_at__isnull=True, + played_at__isnull=True) + + def next_request(self): + return self.unplayed().earliest('created_date') diff --git a/savepointradio/profiles/migrations/0001_initial.py b/savepointradio/profiles/migrations/0001_initial.py new file mode 100644 index 0000000..9a53e86 --- /dev/null +++ b/savepointradio/profiles/migrations/0001_initial.py @@ -0,0 +1,75 @@ +# Generated by Django 2.0 on 2018-01-18 17:36 + +from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('radio', '0002_naming_and_sorting'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='RadioProfile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_date', models.DateTimeField(auto_now_add=True, verbose_name='added on')), + ('modified_date', models.DateTimeField(auto_now=True, verbose_name='last modified')), + ('favorites', models.ManyToManyField(related_name='song_favorites', to='radio.Song')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Rating', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_date', models.DateTimeField(auto_now_add=True, verbose_name='added on')), + ('modified_date', models.DateTimeField(auto_now=True, verbose_name='last modified')), + ('value', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(5)], verbose_name='song rating')), + ('profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rating_profile', to='profiles.RadioProfile')), + ('song', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='radio.Song')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='SongRequest', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_date', models.DateTimeField(auto_now_add=True, verbose_name='added on')), + ('modified_date', models.DateTimeField(auto_now=True, verbose_name='last modified')), + ('queued_at', models.DateTimeField(blank=True, default=None, null=True, verbose_name='song queued at')), + ('played_at', models.DateTimeField(blank=True, default=None, null=True, verbose_name='song played at')), + ('profile', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='request_profile', to='profiles.RadioProfile')), + ('song', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='radio.Song')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='radioprofile', + name='ratings', + field=models.ManyToManyField(related_name='song_ratings', through='profiles.Rating', to='radio.Song'), + ), + migrations.AddField( + model_name='radioprofile', + name='song_requests', + field=models.ManyToManyField(related_name='song_requests', through='profiles.SongRequest', to='radio.Song'), + ), + migrations.AddField( + model_name='radioprofile', + name='user', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/savepointradio/profiles/migrations/__init__.py b/savepointradio/profiles/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/savepointradio/profiles/models.py b/savepointradio/profiles/models.py new file mode 100644 index 0000000..94eeeef --- /dev/null +++ b/savepointradio/profiles/models.py @@ -0,0 +1,78 @@ +from django.conf import settings +from django.core.validators import (MaxLengthValidator, MinValueValidator, + MaxValueValidator) +from django.db import models +from django.db.models.signals import post_save +from django.dispatch import receiver +from django.utils.translation import ugettext_lazy as _ + +from core.behaviors import Timestampable +from radio.models import Song +from .managers import RequestManager + + +class RadioProfile(Timestampable, models.Model): + user = models.OneToOneField(settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + null=True, + blank=True) + favorites = models.ManyToManyField(Song, related_name='song_favorites') + ratings = models.ManyToManyField(Song, + related_name='song_ratings', + through='Rating') + song_requests = models.ManyToManyField(Song, + related_name='song_requests', + through='SongRequest') + + def __str__(self): + return "{}'s profile".format(self.user.get_username()) + + +@receiver(post_save, sender=settings.AUTH_USER_MODEL) +def create_profile(sender, instance, created, **kwargs): + if created: + profile, new = RadioProfile.objects.get_or_create(user=instance) + + +class Rating(Timestampable, models.Model): + profile = models.ForeignKey(RadioProfile, + on_delete=models.CASCADE, + related_name='rating_profile') + song = models.ForeignKey(Song, on_delete=models.CASCADE) + value = models.PositiveIntegerField(_('song rating'), + validators=[MinValueValidator(1), + MaxValueValidator(5)]) + + def __str__(self): + return "{} - {}'s Rating: {}".format(self.song.title, + self.profile.user.get_username(), + self.value) + + +class SongRequest(Timestampable, models.Model): + profile = models.ForeignKey(RadioProfile, + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name='request_profile') + song = models.ForeignKey(Song, + on_delete=models.SET_NULL, + null=True, + blank=True) + queued_at = models.DateTimeField(_('song queued at'), + default=None, + blank=True, + null=True) + played_at = models.DateTimeField(_('song played at'), + default=None, + blank=True, + null=True) + + objects = models.Manager() + music = RequestManager() + + def __str__(self): + req_user = self.profile.user.get_username() + return "{} - Requested by {} at {}".format(self.song.title, + req_user, + self.created_date) diff --git a/savepointradio/profiles/tests.py b/savepointradio/profiles/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/savepointradio/profiles/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/savepointradio/profiles/views.py b/savepointradio/profiles/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/savepointradio/profiles/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/savepointradio/savepointradio/settings/base.py b/savepointradio/savepointradio/settings/base.py index ac3137e..ad6d135 100644 --- a/savepointradio/savepointradio/settings/base.py +++ b/savepointradio/savepointradio/settings/base.py @@ -41,6 +41,7 @@ INSTALLED_APPS = [ 'core.apps.CoreConfig', 'radio.apps.RadioConfig', + 'profiles.apps.ProfilesConfig' ] LANGUAGE_CODE = 'en-us'