/
model.py
163 lines (104 loc) · 5.99 KB
/
model.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
"""Models and database functions for music db."""
from flask_sqlalchemy import SQLAlchemy
# Instantiate SQLAlchemy object, bound to variable "db".
db = SQLAlchemy()
##############################################################################
# Compose ORM.
# Relying on Genius' ids.
class Producer(db.Model):
"""Producer model."""
__tablename__ = "producers"
# Primary keys are inherently unique.
producer_id = db.Column(db.Integer, nullable=False, primary_key=True)
producer_name = db.Column(db.Text, nullable=False)
producer_img_url = db.Column(db.Text, nullable=True)
producer_tag_url = db.Column(db.Text, nullable=True)
# Establish relationships.
# The Producer class has an albums attribute that is a list of Album objects
# using the relationship defined and "produce_song" as the association table
# Attributes are plural to communicate cardinaltiy: ie. a producer can have
# many songs and albums.
songs = db.relationship("Song", secondary="produce_songs", backref="producers")
albums = db.relationship("Album", secondary="produce_songs", backref="producers")
performers = db.relationship("Performer", secondary="produce_songs", backref="producers")
def __repr__(self):
"""Provide helpful representation when printed."""
return f"<Producer producer_id={self.producer_id} producer_name={self.producer_name} producer_img_url={self.producer_img_url} producer_tag_url={self.producer_tag_url}>" # pyflakes does not like f-string; it prefers .format()
@classmethod
def get_producer_songs(cls, producer_name):
return cls.query.filter(cls.producer_name == producer_name).options(db.joinedload("songs")).first()
class Performer(db.Model):
"""Performer model."""
__tablename__ = "performers"
performer_id = db.Column(db.Integer, nullable=False, primary_key=True)
performer_name = db.Column(db.Text, nullable=False)
performer_img_url = db.Column(db.Text, nullable=True)
songs = db.relationship("Song", secondary="produce_songs", backref="performers")
albums = db.relationship("Album", secondary="produce_songs", backref="performers")
def __repr__(self):
return f"<Performer performer_id={self.performer_id} performer_name={self.performer_name} performer_img_url={self.performer_img_url}>"
@classmethod
def get_performer_songs(cls, performer_name):
return cls.query.filter(cls.performer_name == performer_name).options(db.joinedload("songs")).first()
class Song(db.Model):
"""Song model."""
__tablename__ = "songs"
song_id = db.Column(db.Integer, nullable=False, primary_key=True)
song_title = db.Column(db.Text, nullable=False)
apple_music_player_url = db.Column(db.Text, nullable=True)
song_release_date = db.Column(db.DateTime, nullable=True)
song_release_year = db.Column(db.Text, nullable=True)
# song_release_month = db.Column(db.DateTime, nullable=True)
# song_release_day = db.Column(db.DateTime, nullable=True)
def __repr__(self):
return f"<Song song_id={self.song_id} song_title={self.song_title} apple_music_player_url={self.apple_music_player_url} song_release_date={self.song_release_date} song_release_year={self.song_release_year}>"
@classmethod
def get_song_producers(cls, song_title):
return cls.query.filter(cls.song_title == song_title).options(db.joinedload("producers")).all()
class Album(db.Model):
"""Album model."""
__tablename__ = "albums"
album_id = db.Column(db.Integer, nullable=False, primary_key=True)
album_title = db.Column(db.Text, nullable=False)
cover_art_url = db.Column(db.Text, nullable=True)
album_release_date = db.Column(db.DateTime, nullable=True)
songs = db.relationship("Song", secondary="produce_songs", backref="albums")
def __repr__(self):
return f"<Album album_id={self.album_id} album_title={self.album_title} cover_art_url={self.cover_art_url} release_date={self.album_release_date}>"
@classmethod
def get_album_producers(cls, album_title):
return cls.query.filter(cls.album_title == album_title).options(db.joinedload("producers")).all()
class ProduceSong(db.Model):
"""ProduceSong model."""
__tablename__ = "produce_songs"
event_id = db.Column(db.Integer, autoincrement=True, nullable=False, primary_key=True)
producer_id = db.Column(db.Integer, db.ForeignKey('producers.producer_id'), nullable=False)
performer_id = db.Column(db.Integer, db.ForeignKey('performers.performer_id'), nullable=False)
song_id = db.Column(db.Integer, db.ForeignKey('songs.song_id'), nullable=False)
album_id = db.Column(db.Integer, db.ForeignKey('albums.album_id'), nullable=True)
# Because there is only one performer per song, a 1 to 1 relationship is
# established with performer.
# ProduceSong has an attribute performer that is a Performer object
# using the produce_songs reference (there is a direct relationship) between
# Performer and ProduceSong which is the performer_id.
# Performer can have multiple songs.
performers = db.relationship("Performer", backref="produce_songs")
# albums = db.relationship("Album", backref="produce_songs")
def __repr__(self):
return f"<ProduceSong event_id={self.event_id} producer_id={self.producer_id} performer_id={self.performer_id} song_id={self.song_id} album_id={self.album_id}>"
# may add Users class in 3.0
##############################################################################
def connect_to_db(app):
"""Connect the database to Flask app."""
# Configure to use database.
# Creates database when entering psql music at commandline.
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///music'
app.config['SQLALCHEMY_ECHO'] = False
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.app = app
db.init_app(app)
if __name__ == "__main__":
# Added for module interactive convenience to work directly with database.
from server import app
connect_to_db(app)
print("Connected to DB.")