Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 489 lines (407 sloc) 16.946 kB
04bbedb @alexkay Copyright header
authored
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright © 2009-2011 Alexander Kojevnikov <alexander@kojevnikov.com>
4 #
5 # muspy is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # muspy is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Affero General Public License for more details.
14 #
15 # You should have received a copy of the GNU Affero General Public License
16 # along with muspy. If not, see <http://www.gnu.org/licenses/>.
17
a72c4ca @alexkay Email activation
authored
18 import random
c5912e9 @alexkay daemon: Send email notifications
authored
19 from smtplib import SMTPException
7c2341c @alexkay Add UserArtists
authored
20 from time import sleep
a72c4ca @alexkay Email activation
authored
21
b14d6ea @alexkay Sign up / sign in /sign out
authored
22 from django.contrib.auth.models import User
a72c4ca @alexkay Email activation
authored
23 from django.core.mail import EmailMultiAlternatives
cbc53df @alexkay Delete account
authored
24 from django.db import connection, IntegrityError, models, transaction
6bbd228 @alexkay PRAGMA foreign_keys=1
authored
25 from django.db.backends.signals import connection_created
778944b @alexkay Initialise and sort by is_starred
authored
26 from django.db.models import Count, Q
47c91b7 @alexkay Add UserProfile
authored
27 from django.db.models.signals import post_save
6bbd228 @alexkay PRAGMA foreign_keys=1
authored
28 from django.dispatch import receiver
a72c4ca @alexkay Email activation
authored
29 from django.template.loader import render_to_string
6bbd228 @alexkay PRAGMA foreign_keys=1
authored
30
7c2341c @alexkay Add UserArtists
authored
31 import app.musicbrainz as mb
994a74d @alexkay Add the atom feed for new releases
authored
32 from app.tools import date_to_iso8601, date_to_str, str_to_date
7c2341c @alexkay Add UserArtists
authored
33
97bdbd5 @alexkay Star release groups
authored
34
13e32ee @alexkay Add Artist and ReleaseGroup models
authored
35 class Artist(models.Model):
c0ebc69 @alexkay Add an empty app
authored
36
13e32ee @alexkay Add Artist and ReleaseGroup models
authored
37 mbid = models.CharField(max_length=36, unique=True)
38 name = models.CharField(max_length=512)
39 sort_name = models.CharField(max_length=512)
40 disambiguation = models.CharField(max_length=512)
be118e8 @alexkay Make UserArtist a ManyToManyField
authored
41 users = models.ManyToManyField(User, through='UserArtist')
a72c4ca @alexkay Email activation
authored
42
449d6cc @alexkay Blacklist special-purpose artists
authored
43 blacklisted = [
44 '89ad4ac3-39f7-470e-963a-56509c546377', # Various Artists
aa0f948 @alexkay Block more special-purpose artists
authored
45 'fe5b7087-438f-4e7e-afaf-6d93c8c888b2', # Various Artists
449d6cc @alexkay Blacklist special-purpose artists
authored
46 'f731ccc4-e22a-43af-a747-64213329e088', # [anonymous]
47 '33cf029c-63b0-41a0-9855-be2a3665fb3b', # [data]
48 '314e1c25-dde7-4e4d-b2f4-0a7b9f7c56dc', # [dialogue]
49 'eec63d3c-3b81-4ad4-b1e4-7c147d4d2b61', # [no artist]
50 '9be7f096-97ec-4615-8957-8d40b5dcbc41', # [traditional]
51 '125ec42a-7229-4250-afc5-e057484327fe', # [unknown]
aa0f948 @alexkay Block more special-purpose artists
authored
52 '203b6058-2401-4bf0-89e3-8dc3d37c3f12', # [unknown]
53 '5e760f5a-ea55-4b53-a18f-021c0d9779a6', # [unknown]
49aa02f @alexkay Block even more special-purpose artists
authored
54 '1d8bc797-ec8a-40d2-8d80-b1346b56a65f', # [unknown]
55 '7734d67f-44d9-4ba2-91e3-9b067263210e', # [unknown]
e056496 @alexkay Black list [soundtrack]
authored
56 'd6bd72bc-b1e2-4525-92aa-0f853cbb41bf', # [soundtrack]
449d6cc @alexkay Blacklist special-purpose artists
authored
57 ]
58 class Blacklisted(Exception): pass
87c4ecb @alexkay Handle unknown artists
authored
59 class Unknown(Exception): pass
449d6cc @alexkay Blacklist special-purpose artists
authored
60
57ddf35 @alexkay Show added artists
authored
61 @classmethod
4c642cc @alexkay Show artist's release groups
authored
62 def get_by_mbid(cls, mbid):
7c2341c @alexkay Add UserArtists
authored
63 """ Fetches the artist and releases from MB if not in the database. """
449d6cc @alexkay Blacklist special-purpose artists
authored
64 if mbid in cls.blacklisted:
65 raise cls.Blacklisted()
66
4c642cc @alexkay Show artist's release groups
authored
67 try:
68 return cls.objects.get(mbid=mbid)
69 except cls.DoesNotExist:
7c2341c @alexkay Add UserArtists
authored
70 pass
71
72 artist_data = mb.get_artist(mbid)
87c4ecb @alexkay Handle unknown artists
authored
73 if artist_data is None:
4c642cc @alexkay Show artist's release groups
authored
74 return None
87c4ecb @alexkay Handle unknown artists
authored
75 if not artist_data:
76 raise cls.Unknown
4c642cc @alexkay Show artist's release groups
authored
77
7c2341c @alexkay Add UserArtists
authored
78 artist = Artist(
79 mbid=mbid, name=artist_data['name'], sort_name=artist_data['sort-name'],
10a8992 @alexkay daemon: Update artist info
authored
80 disambiguation=artist_data.get('disambiguation', ''))
2401aac @alexkay Fix occasional integrity errors
authored
81 try:
82 artist.save()
83 except IntegrityError:
84 # The artist was added while we were querying MB.
85 return cls.objects.get(mbid=mbid)
7c2341c @alexkay Add UserArtists
authored
86
87 # Add a few release groups immediately.
2401aac @alexkay Fix occasional integrity errors
authored
88 # Sleep 1s to comply with the MB web service.
89 sleep(1)
529eca9 @alexkay Add all release groups for new artists
authored
90 LIMIT = 100
91 release_groups = mb.get_release_groups(mbid, limit=LIMIT, offset=0)
7c2341c @alexkay Add UserArtists
authored
92 if release_groups:
93 with transaction.commit_on_success():
94 for rg_data in release_groups:
e14b44e @alexkay daemon: Implement ADD_ARTIST and ADD_RELEASE_GROUP jobs
authored
95 # Ignoring releases without a release date or a type.
96 if rg_data.get('first-release-date') and rg_data.get('type'):
7c2341c @alexkay Add UserArtists
authored
97 release_group = ReleaseGroup(
98 artist=artist,
99 mbid=rg_data['id'],
100 name=rg_data['title'],
101 type=rg_data['type'],
c05a3b0 @alexkay Calendar
authored
102 date=str_to_date(rg_data['first-release-date']),
7c2341c @alexkay Add UserArtists
authored
103 is_deleted=False)
9af209c @alexkay Multiple artists per release group
authored
104 release_group.save()
529eca9 @alexkay Add all release groups for new artists
authored
105
106 if release_groups is None or len(release_groups) == LIMIT:
107 # Add the remaining release groups
108 Job.add_release_groups(artist)
109
7c2341c @alexkay Add UserArtists
authored
110 return artist
111
4c642cc @alexkay Show artist's release groups
authored
112 @classmethod
57ddf35 @alexkay Show added artists
authored
113 def get_by_user(cls, user):
114 # TODO: paging
be118e8 @alexkay Make UserArtist a ManyToManyField
authored
115 return cls.objects.filter(users=user).order_by('sort_name')[:1000]
57ddf35 @alexkay Show added artists
authored
116
97bdbd5 @alexkay Star release groups
authored
117
3b047a0 @alexkay Job model
authored
118 class Job(models.Model):
119
b1876ee @alexkay Add multiple artists
authored
120 ADD_ARTIST = 1
529eca9 @alexkay Add all release groups for new artists
authored
121 ADD_RELEASE_GROUPS = 2
f41cab4 @alexkay Show empty album cover
authored
122 GET_COVER = 3
123 IMPORT_LASTFM = 4
3b047a0 @alexkay Job model
authored
124
529eca9 @alexkay Add all release groups for new artists
authored
125 user = models.ForeignKey(User, null=True)
3b047a0 @alexkay Job model
authored
126 type = models.IntegerField()
127 data = models.TextField()
128
b1876ee @alexkay Add multiple artists
authored
129 @classmethod
130 def add_artists(cls, user, names):
131 with transaction.commit_on_success():
132 for name in names:
133 cls(user=user, type=cls.ADD_ARTIST, data=name).save()
134
529eca9 @alexkay Add all release groups for new artists
authored
135 @classmethod
136 def add_release_groups(cls, artist):
137 cls(user=None, type=cls.ADD_RELEASE_GROUPS, data=artist.mbid).save()
b1876ee @alexkay Add multiple artists
authored
138
f41cab4 @alexkay Show empty album cover
authored
139 @classmethod
140 def get_cover(cls, mbid):
141 cls(user=None, type=cls.GET_COVER, data=mbid).save()
142
2db316b @alexkay Import artists from Last.fm
authored
143 @classmethod
6b5a789 @alexkay Allow to specify the period when importing from Last.fm
authored
144 def import_lastfm(cls, user, username, count, period):
145 data = str(count) + ',' + period + ',' + username
146 cls(user=user, type=cls.IMPORT_LASTFM, data=data).save()
2db316b @alexkay Import artists from Last.fm
authored
147
148 @classmethod
149 def importing_artists(cls, user):
150 """Returns a comma-separated list of all artists yet to be imported."""
151 q = cls.objects.filter(user=user)
152 q = q.filter(type=cls.ADD_ARTIST)
153 return [r.data for r in q]
154
155 @classmethod
156 def has_import_lastfm(cls, user):
157 return cls.objects.filter(user=user).filter(type=cls.IMPORT_LASTFM).exists()
158
f41cab4 @alexkay Show empty album cover
authored
159
861ddc0 @alexkay Add the Notification model
authored
160 class Notification(models.Model):
161
162 class Meta:
163 db_table = 'app_notification'
164 unique_together = ('user', 'release_group')
165
166 user = models.ForeignKey(User)
167 release_group = models.ForeignKey('ReleaseGroup')
168
14bc2b2 @alexkay daemon: Add Notifications
authored
169
13e32ee @alexkay Add Artist and ReleaseGroup models
authored
170 class ReleaseGroup(models.Model):
9af209c @alexkay Multiple artists per release group
authored
171 """De-normalised release groups
172
173 A release group can have different artists. Instead of adding a
174 many-to-many relationship between them, keep everything in one
175 table and group by mbid as needed.
176
177 """
178 class Meta:
179 unique_together = ('artist', 'mbid')
13e32ee @alexkay Add Artist and ReleaseGroup models
authored
180
181 artist = models.ForeignKey(Artist)
9af209c @alexkay Multiple artists per release group
authored
182 mbid = models.CharField(max_length=36)
13e32ee @alexkay Add Artist and ReleaseGroup models
authored
183 name = models.CharField(max_length=512)
184 type = models.CharField(max_length=16)
185 date = models.IntegerField() # 20080101 OR 20080100 OR 20080000
186 is_deleted = models.BooleanField()
861ddc0 @alexkay Add the Notification model
authored
187
188 users_who_starred = models.ManyToManyField(
189 User, through='Star', related_name='starred_release_groups')
190 users_to_notify = models.ManyToManyField(
191 User, through='Notification', related_name='new_release_groups')
47c91b7 @alexkay Add UserProfile
authored
192
4c642cc @alexkay Show artist's release groups
authored
193 def date_str(self):
c05a3b0 @alexkay Calendar
authored
194 return date_to_str(self.date)
4c642cc @alexkay Show artist's release groups
authored
195
994a74d @alexkay Add the atom feed for new releases
authored
196 def date_iso8601(self):
197 return date_to_iso8601(self.date)
198
4c642cc @alexkay Show artist's release groups
authored
199 @classmethod
f026ba0 @alexkay Fixes
authored
200 def get(cls, artist=None, user=None, limit=0, offset=0, feed=False):
994a74d @alexkay Add the atom feed for new releases
authored
201 if not artist and not user:
202 assert 'Both artist and user are None'
203 return None
cab32cf @alexkay Fix ReleaseGroup.get()
authored
204
205 # Unfortunately I don't see how to use ORM for these queries.
206 sql = """
207 SELECT
208 "app_releasegroup"."id",
209 "app_releasegroup"."artist_id",
210 "app_releasegroup"."mbid",
211 "app_releasegroup"."name",
212 "app_releasegroup"."type",
213 "app_releasegroup"."date",
214 "app_releasegroup"."is_deleted",
215 "app_artist"."mbid" AS "artist_mbid",
ca5d2b1 @alexkay api: GET releases
authored
216 "app_artist"."name" AS "artist_name",
217 "app_artist"."sort_name" AS "artist_sort_name",
218 "app_artist"."disambiguation" AS "artist_disambiguation"
cab32cf @alexkay Fix ReleaseGroup.get()
authored
219 {select}
220 FROM "app_releasegroup"
221 JOIN "app_artist" ON "app_artist"."id" = "app_releasegroup"."artist_id"
222 {join}
223 WHERE "app_releasegroup"."is_deleted" = 0
224 {where}
225 ORDER BY {order}
30f54c9 @alexkay Optimise ReleaseGroup.get()
authored
226 LIMIT %s OFFSET %s
cab32cf @alexkay Fix ReleaseGroup.get()
authored
227 """
228 select = join = where = ''
229 order = '"app_releasegroup"."date" DESC'
230 params = []
994a74d @alexkay Add the atom feed for new releases
authored
231 if artist:
cab32cf @alexkay Fix ReleaseGroup.get()
authored
232 where += '\nAND "app_releasegroup"."artist_id" = %s'
233 params.append(artist.id)
994a74d @alexkay Add the atom feed for new releases
authored
234 if user:
cab32cf @alexkay Fix ReleaseGroup.get()
authored
235 # Stars.
236 select += ',\n"app_star"."id" as "is_starred"'
237 join += '\nJOIN "app_userartist" ON "app_userartist"."artist_id" = "app_artist"."id"'
238 join += '\nLEFT JOIN "app_star" ON "app_star"."user_id" = "app_userartist"."user_id" AND "app_star"."release_group_id" = "app_releasegroup"."id"'
239 where += '\nAND "app_userartist"."user_id" = %s'
240 params.append(user.id)
64cb5b2 @alexkay Fix stars sort order
authored
241 order = '"app_star"."user_id" DESC, ' + order
cab32cf @alexkay Fix ReleaseGroup.get()
authored
242 # Release types.
ca9679d @alexkay Don't show duplicate releases for imported users
authored
243 profile = user.get_profile()
cab32cf @alexkay Fix ReleaseGroup.get()
authored
244 types = profile.get_types()
245 ss = ','.join('%s' for i in xrange(len(types)))
246 where += '\nAND "app_releasegroup"."type" IN (' + ss + ')'
247 params.extend(types)
248
f026ba0 @alexkay Fixes
authored
249 if feed and profile.legacy_id:
ca9679d @alexkay Don't show duplicate releases for imported users
authored
250 # Don't include release groups added during the import
cab32cf @alexkay Fix ReleaseGroup.get()
authored
251 # TODO: Feel free to remove this check some time in 2013.
252 where += '\nAND "app_releasegroup"."id" > 261202'
253
254 sql = sql.format(select=select, join=join, where=where, order=order)
30f54c9 @alexkay Optimise ReleaseGroup.get()
authored
255 params.extend([limit, offset])
256 return cls.objects.raw(sql, params)
4c642cc @alexkay Show artist's release groups
authored
257
258 @classmethod
c05a3b0 @alexkay Calendar
authored
259 def get_calendar(cls, date, limit, offset):
260 """Returns the list of release groups for the date."""
261 q = cls.objects.filter(date__lte=date)
cab32cf @alexkay Fix ReleaseGroup.get()
authored
262 q = q.select_related('artist')
263 # Calendar uses the same template as releases, adapt to conform.
264 q = q.extra(select={
265 'artist_mbid': '"app_artist"."mbid"',
ca5d2b1 @alexkay api: GET releases
authored
266 'artist_name': '"app_artist"."name"',
267 'artist_sort_name': '"app_artist"."sort_name"',
268 'artist_disambiguation': '"app_artist"."disambiguation"',
269 })
c05a3b0 @alexkay Calendar
authored
270 q = q.filter(is_deleted=False)
496db6a @alexkay Optimise ReleaseGroup.get_calendar()
authored
271 q = q.order_by('-date')
c05a3b0 @alexkay Calendar
authored
272 return q[offset:offset+limit]
4c642cc @alexkay Show artist's release groups
authored
273
97bdbd5 @alexkay Star release groups
authored
274
275 class Star(models.Model):
276
277 class Meta:
778944b @alexkay Initialise and sort by is_starred
authored
278 db_table = 'app_star'
97bdbd5 @alexkay Star release groups
authored
279 unique_together = ('user', 'release_group')
280
281 user = models.ForeignKey(User)
282 release_group = models.ForeignKey(ReleaseGroup)
283
284 @classmethod
4930247 @alexkay Fix starring
authored
285 def set(cls, user, id, value):
97bdbd5 @alexkay Star release groups
authored
286 try:
4930247 @alexkay Fix starring
authored
287 release_group = ReleaseGroup.objects.get(id=id)
97bdbd5 @alexkay Star release groups
authored
288 except ReleaseGroup.DoesNotExist:
289 return
290 if value:
291 cls.objects.get_or_create(user=user, release_group=release_group)
292 else:
293 cls.objects.filter(user=user, release_group=release_group).delete()
294
be118e8 @alexkay Make UserArtist a ManyToManyField
authored
295
0915072 @alexkay Add UserArtist model
authored
296 class UserArtist(models.Model):
297
298 class Meta:
299 unique_together = ('user', 'artist')
300
301 user = models.ForeignKey(User)
302 artist = models.ForeignKey(Artist)
7c2341c @alexkay Add UserArtists
authored
303 date = models.DateTimeField(auto_now_add=True)
304
305 @classmethod
3ae58f8 @alexkay Filter releases by user when authenticated
authored
306 def get(cls, user, artist):
307 try:
308 return cls.objects.get(user=user, artist=artist)
309 except cls.DoesNotExist:
310 return None
311
312 @classmethod
7c2341c @alexkay Add UserArtists
authored
313 def add(cls, user, artist):
314 user_artist = cls(user=user, artist=artist)
315 try:
316 user_artist.save()
317 except IntegrityError:
318 pass
0915072 @alexkay Add UserArtist model
authored
319
3ec7885 @alexkay Remove UserArtists
authored
320 @classmethod
321 def remove(cls, user, mbids):
322 with transaction.commit_on_success():
323 for mbid in mbids:
4930247 @alexkay Fix starring
authored
324 q = cls.objects.filter(user=user)
3ec7885 @alexkay Remove UserArtists
authored
325 q = q.filter(artist__mbid=mbid)
326 q.delete()
327
97bdbd5 @alexkay Star release groups
authored
328
47c91b7 @alexkay Add UserProfile
authored
329 class UserProfile(models.Model):
330
a72c4ca @alexkay Email activation
authored
331 code_length = 16
332
47c91b7 @alexkay Add UserProfile
authored
333 user = models.OneToOneField(User)
334
335 notify = models.BooleanField(default=True)
336 notify_album = models.BooleanField(default=True)
337 notify_single = models.BooleanField(default=True)
338 notify_ep = models.BooleanField(default=True)
339 notify_live = models.BooleanField(default=True)
340 notify_compilation = models.BooleanField(default=True)
341 notify_remix = models.BooleanField(default=True)
342 notify_other = models.BooleanField(default=True)
343 email_activated = models.BooleanField(default=False)
a72c4ca @alexkay Email activation
authored
344 activation_code = models.CharField(max_length=code_length)
345 reset_code = models.CharField(max_length=code_length)
b296691 @alexkay Add UserProfile.legacy_id, tidy
authored
346 legacy_id = models.IntegerField(null=True)
47c91b7 @alexkay Add UserProfile
authored
347
34a19ef @alexkay Filter user releases by type
authored
348 def get_types(self):
349 """Return the list of release types the user wants to follow."""
350 types = []
351 if self.notify_album: types.append('Album')
352 if self.notify_single: types.append('Single')
353 if self.notify_ep: types.append('EP')
354 if self.notify_live: types.append('Live')
355 if self.notify_compilation: types.append('Compilation')
356 if self.notify_remix: types.append('Remix')
357 if self.notify_other:
358 types.extend(['Soundtrack', 'Spokenword', 'Interview', 'Audiobook', 'Other'])
359 return types
360
a72c4ca @alexkay Email activation
authored
361 def generate_code(self):
362 code_chars = '23456789abcdefghijkmnpqrstuvwxyz'
363 return ''.join(random.choice(code_chars) for i in xrange(UserProfile.code_length))
364
cbc53df @alexkay Delete account
authored
365 def purge(self):
366 user = self.user
367 with transaction.commit_on_success():
368 Job.objects.filter(user=user).delete()
369 Notification.objects.filter(user=user).delete()
370 Star.objects.filter(user=user).delete()
371 UserArtist.objects.filter(user=user).delete()
372 UserSearch.objects.filter(user=user).delete()
373 self.delete()
374 # Cannot call user.delete() because it references deprecated auth_message.
375 cursor = connection.cursor()
376 cursor.execute('DELETE FROM auth_user WHERE id=%s', [user.id])
377
a72c4ca @alexkay Email activation
authored
378 def send_email(self, subject, text_template, html_template, **kwds):
379 text = render_to_string(text_template, kwds)
3b4ccca @alexkay Tidy
authored
380 msg = EmailMultiAlternatives(
381 subject,
382 text,
383 'muspy support <info@muspy.com>',
384 [self.user.email])
a72c4ca @alexkay Email activation
authored
385 if html_template:
386 html = render_to_string(html_template, kwds)
c5912e9 @alexkay daemon: Send email notifications
authored
387 msg.attach_alternative(html, "text/html")
388 try:
389 msg.send()
390 except SMTPException:
391 return False
392 return True
a72c4ca @alexkay Email activation
authored
393
394 def send_activation_email(self):
395 code = self.generate_code()
396 self.activation_code = code
397 self.save()
c5912e9 @alexkay daemon: Send email notifications
authored
398 self.send_email(
399 subject='Email Activation',
400 text_template='email/activate.txt',
401 html_template=None,
402 code=code)
a72c4ca @alexkay Email activation
authored
403
404 def send_reset_email(self):
405 code = self.generate_code()
406 self.reset_code = code
407 self.save()
c5912e9 @alexkay daemon: Send email notifications
authored
408 self.send_email(
409 subject='Password Reset Confirmation',
410 text_template='email/reset.txt',
411 html_template=None,
412 code=code)
a72c4ca @alexkay Email activation
authored
413
414 @classmethod
415 def activate(cls, code):
b296691 @alexkay Add UserProfile.legacy_id, tidy
authored
416 profiles = UserProfile.objects.filter(activation_code=code)
a72c4ca @alexkay Email activation
authored
417 if not profiles:
418 return False
419 profile = profiles[0]
420 profile.activation_code = ''
421 profile.email_activated = True
422 profile.save()
423 return True
424
425 @classmethod
426 def reset(cls, code):
b296691 @alexkay Add UserProfile.legacy_id, tidy
authored
427 profiles = UserProfile.objects.filter(reset_code=code)
e4e6368 @alexkay Password reset fixes
authored
428 if not profiles:
a72c4ca @alexkay Email activation
authored
429 return None, None
e4e6368 @alexkay Password reset fixes
authored
430 profile = profiles[0]
431 password = User.objects.make_random_password(length=16)
a72c4ca @alexkay Email activation
authored
432 profile.reset_code = ''
433 profile.user.set_password(password)
6521508 @alexkay Save the user and the profile within a transaction
authored
434 with transaction.commit_on_success():
435 profile.user.save()
436 profile.save()
a72c4ca @alexkay Email activation
authored
437 return profile.user.email, password
438
439 @classmethod
b296691 @alexkay Add UserProfile.legacy_id, tidy
authored
440 def get_by_email(cls, email):
441 users = User.objects.filter(email=email.lower())
442 return users[0].get_profile() if users else None
443
444 @classmethod
445 def get_by_legacy_id(cls, legacy_id):
446 profiles = cls.objects.filter(legacy_id=legacy_id)
447 return profiles[0] if profiles else None
448
449 @classmethod
450 def get_by_username(cls, username):
451 users = User.objects.filter(username=username)
a72c4ca @alexkay Email activation
authored
452 return users[0].get_profile() if users else None
13e32ee @alexkay Add Artist and ReleaseGroup models
authored
453
97bdbd5 @alexkay Star release groups
authored
454
b1876ee @alexkay Add multiple artists
authored
455 class UserSearch(models.Model):
456
457 user = models.ForeignKey(User)
458 search = models.CharField(max_length=512)
459
460 @classmethod
461 def get(cls, user):
462 return cls.objects.filter(user=user)
463
2f500a9 @alexkay Remove user searches
authored
464 @classmethod
465 def remove(cls, user, searches):
466 with transaction.commit_on_success():
467 for search in searches:
468 cls.objects.filter(user=user, search=search).delete()
469
b1876ee @alexkay Add multiple artists
authored
470
13e32ee @alexkay Add Artist and ReleaseGroup models
authored
471 # Activate foreign keys for sqlite.
472 @receiver(connection_created)
473 def activate_foreign_keys(sender, connection, **kwargs):
474 if connection.vendor == 'sqlite':
475 cursor = connection.cursor()
476 cursor.execute('PRAGMA foreign_keys=1;')
477
97bdbd5 @alexkay Star release groups
authored
478
13e32ee @alexkay Add Artist and ReleaseGroup models
authored
479 # Create a profile for each user.
480 @receiver(post_save, sender=User)
481 def user_post_save(sender, instance, created, **kwargs):
482 if created:
483 p = UserProfile()
484 p.user = instance
485 p.save()
486
97bdbd5 @alexkay Star release groups
authored
487
13e32ee @alexkay Add Artist and ReleaseGroup models
authored
488 User.__unicode__ = lambda x: x.email
Something went wrong with that request. Please try again.