Commit 1f1d25b2 authored by Brian Guadalupe's avatar Brian Guadalupe

Merge branch 'create-playlist' into 'master'

Add unique email constraint for User

See merge request brian/mymusiclist!11
parents 95b54b6b f988e490
# MyMusicList
This is a work in progress as of now...
**IMPORTANT: Please read the contribution guide (`CONTRIBUTING.md`) first before pushing to this repo! Any unnecessary commits to the `master` branch will be immediately reverted.**
## Prerequisites
* Python 2.7/3.4 or later
* `virtualenv` (preferred)
* SQLite3 (for testing)
* Add the `sqlite3` executable in your `PATH`
* MySQL (for the final version)
## Setup
This assumes both Python and Git have been already installed and added to the `PATH`.
1. Clone the MyMusicList repo from `https://gitlab.discs.ateneo.edu/brian/mymusiclist` using Git
* `git clone https://gitlab.discs.ateneo.edu/brian/mymusiclist`
2. Install the latest version of `virtualenv`
* `pip install virtualenv`
3. Setup the Python virtual environment; you can opt to use any name you prefer
* `virtualenv venv`
4. Activate the virtualenv
* *`path\to\venv\`*`Scripts\activate` (for Windows)
* `. `*`path/to/venv/`*`bin/activate` (for Linux/Mac OS)
5. Install Django using `pip` (inside the virtualenv)
* `pip install django`
6. Make sure that the `migrations` folder is empty except for the `__init__.py` file
7. Delete the `db.sqlite3` file if it exists
8. Run the following commands (inside the virtualenv):
* `python manage.py makemigrations core playlist search tag user`
* `python manage.py migrate`
9. Open the `db.sqlite3` file in sqlite3, and run the following commands:
* *`sqlite> `* `.read SQL/sqlite3.sql`
* *`sqlite> `* `.quit`
10. Populate the songs database
* Run `python manage.py shell`
* ~~*`>>> `* `exec(open('./SQL/populate_songs.py').read())`~~ DOESN'T WORK YET!
* Instead, copy everything from `populate_songs.py` and then paste into the shell
* *`>>> `* `run()`
* This works for now...
11. Run the web server
* `python manage.py runserver`
12. (Optional) Create admin account to access the admin interface
* `python manage.py createsuperuser`
\ No newline at end of file
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# run in Django shell ONLY!!! # run in Django shell ONLY!!!
# python manage.py shell # python manage.py shell
# >>> exec(open('./SQL/populate_songs.py').read()) # copy-paste everything then
# >>> run()
import time
from core.models import * from core.models import *
def extract_song_title(s): def extract_song_title(s):
...@@ -20,13 +21,59 @@ def extract_song_title(s): ...@@ -20,13 +21,59 @@ def extract_song_title(s):
def prettify_genre(g): def prettify_genre(g):
return ', '.join([h.replace('_',' ') for h in g.split()]) return ', '.join([h.replace('_',' ') for h in g.split()])
for i in Song.objects.filter(song_name__startswith="."): def parse_raw(n_albums):
idx = 1
total_time = 0
for i in Song.objects.filter(song_name__startswith="."):
print('Processing entry %d of %d...' % (idx, n_albums))
t0 = time.time()
songlst = extract_song_title(i.song_name) songlst = extract_song_title(i.song_name)
for e in songlst: for e in songlst:
# print(' FOUND: ' + e)
Song.objects.create(song_name=e, genre=prettify_genre(i.genre), artist=i.artist, album=i.album) Song.objects.create(song_name=e, genre=prettify_genre(i.genre), artist=i.artist, album=i.album)
# uncomment the next line if you want to delete the original entry after parsing tf = time.time()
delta = tf-t0
total_time += delta
# time remaining = (avg time per album)*(# remaining albums)
trem = (total_time/idx)*(n_albums-idx)
print('[INFO] Parsing entry %d took %.3fs' % (idx, delta))
print('[INFO] Approx. time remaining: %d:%02d' % (trem//60, int(trem)%60))
idx += 1
def cleanup(n_albums):
print('Deleting original raw entries...')
didx = 1
for i in Song.objects.filter(song_name__startswith="."):
print('Deleting raw entry %d of %d...' % (didx, n_albums))
i.delete() i.delete()
didx += 1
# if something messed up above, run this
def revert():
rm = len(Song.objects.exclude(song_name__startswith="."))
ridx = 1
ttime = 0
for song in Song.objects.exclude(song_name__startswith="."):
t0 = time.time()
song.delete()
tf = time.time()
delta = tf-t0
ttime += delta
trem = (ttime/ridx)*(rm-ridx)
print('[INFO] Approx. time remaining: %d:%02d' % (trem//60, int(trem)%60))
ridx += 1
def purge_all():
resp = input('[WARN] Delete ALL entries? [y/N] ')
if resp == 'y':
for song in Song.objects.all():
song.delete()
print('[INFO] All entries deleted!')
# if something messed up above, uncomment these lines def run():
# for song in Song.objects.exclude(song_name__startswith="."): print('Populate songs')
# song.delete() qu = Song.objects.filter(song_name__startswith=".")
\ No newline at end of file n_albums = len(qu)
print('Found %d entries yet to be parsed' % n_albums)
parse_raw(n_albums)
cleanup(n_albums)
\ No newline at end of file
from django.db import models from django.db import models
from core.models import * from core.models import *
from user.models import * from django.contrib.auth.models import User
class MusicPlaylist(models.Model): class MusicPlaylist(models.Model):
id = models.AutoField(primary_key=True) id = models.AutoField(primary_key=True)
playlist_name = models.CharField(max_length=32) playlist_name = models.CharField(max_length=32)
is_public = models.BooleanField(default=False) is_public = models.BooleanField(default=False)
user = models.ForeignKey(UserAccount) user = models.ForeignKey(User)
def __str__(self): def __str__(self):
return self.playlist_name return self.playlist_name
......
...@@ -2,7 +2,6 @@ from django import forms ...@@ -2,7 +2,6 @@ from django import forms
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User from django.contrib.auth.models import User
class SignUpForm(UserCreationForm): class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=255) first_name = forms.CharField(max_length=255)
last_name = forms.CharField(max_length=255) last_name = forms.CharField(max_length=255)
...@@ -11,3 +10,10 @@ class SignUpForm(UserCreationForm): ...@@ -11,3 +10,10 @@ class SignUpForm(UserCreationForm):
class Meta: class Meta:
model = User model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2', ) fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2', )
def clean_email(self):
email = self.cleaned_data.get('email')
username = self.cleaned_data.get('username')
if email and User.objects.filter(email=email).exclude(username=username).exists():
raise forms.ValidationError('User with this Email address already exists.')
return email
\ No newline at end of file
from django.db import models from django.db import models
from django.contrib.auth.models import User
class UserAccount(models.Model): # Enforce referential integrity at db level
id = models.AutoField(primary_key=True) User._meta.get_field('email')._unique = True
first_name = models.CharField(max_length=64)
last_name = models.CharField(max_length=64) # class UserAccount(models.Model):
email = models.CharField(max_length=64) # id = models.AutoField(primary_key=True)
# first_name = models.CharField(max_length=64)
# last_name = models.CharField(max_length=64)
# email = models.CharField(max_length=64)
...@@ -29,3 +29,9 @@ class EditProfile(UpdateView): ...@@ -29,3 +29,9 @@ class EditProfile(UpdateView):
slug_field = 'username' slug_field = 'username'
slug_url_kwarg = 'slug' slug_url_kwarg = 'slug'
def clean_email(self):
email = self.cleaned_data.get('email')
username = self.cleaned_data.get('username')
if email and User.objects.filter(email=email).exclude(username=username).exists():
raise forms.ValidationError('This email address has been already used by another user.')
return email
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment