models.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. from django.db import models
  2. from django.core.validators import MinValueValidator, MaxValueValidator
  3. from django.utils import timezone
  4. from django.contrib.auth.models import User
  5. class Musician(models.Model):
  6. musician_id = models.AutoField(primary_key=True)
  7. name = models.CharField(max_length=100, verbose_name="Имя исполнителя")
  8. city = models.CharField(max_length=100, blank=True, null=True)
  9. birth_year = models.IntegerField(null=True, blank=True)
  10. class Meta:
  11. db_table = 'musician'
  12. verbose_name = 'Исполнитель'
  13. verbose_name_plural = 'Исполнители'
  14. def __str__(self):
  15. return self.name
  16. class Genre(models.Model):
  17. genre_id = models.AutoField(primary_key=True)
  18. genre_name = models.CharField(max_length=50, unique=True)
  19. class Meta:
  20. db_table = 'genre'
  21. verbose_name = 'Жанр'
  22. verbose_name_plural = 'Жанры'
  23. def __str__(self):
  24. return self.genre_name
  25. class Album(models.Model):
  26. album_id = models.AutoField(primary_key=True)
  27. album_name = models.CharField(max_length=150)
  28. release_date = models.DateField(null=True, blank=True)
  29. musician = models.ForeignKey(Musician, on_delete=models.CASCADE, db_column='musician_id')
  30. class Meta:
  31. db_table = 'album'
  32. verbose_name = 'Альбом'
  33. verbose_name_plural = 'Альбомы'
  34. indexes = [
  35. models.Index(fields=['musician'], name='idx_album_musician'),
  36. ]
  37. def __str__(self):
  38. return f"{self.album_name} - {self.musician.name}"
  39. class Song(models.Model):
  40. song_id = models.AutoField(primary_key=True)
  41. title = models.CharField(max_length=150)
  42. duration_sec = models.IntegerField(validators=[MinValueValidator(1)], null=True, blank=True)
  43. album = models.ForeignKey(Album, on_delete=models.CASCADE, db_column='album_id')
  44. genre = models.ForeignKey(Genre, on_delete=models.SET_NULL, null=True, db_column='genre_id')
  45. class Meta:
  46. db_table = 'song'
  47. verbose_name = 'Песня'
  48. verbose_name_plural = 'Песни'
  49. indexes = [
  50. models.Index(fields=['album'], name='idx_song_album'),
  51. models.Index(fields=['genre'], name='idx_song_genre'),
  52. ]
  53. def __str__(self):
  54. return self.title
  55. @property
  56. def duration_formatted(self):
  57. """Расчетный атрибут: форматированная длительность"""
  58. if not self.duration_sec:
  59. return "00:00"
  60. minutes = self.duration_sec // 60
  61. seconds = self.duration_sec % 60
  62. return f"{minutes}:{seconds:02d}"
  63. class Meloman(models.Model):
  64. GENDER_CHOICES = [
  65. ('M', 'Мужской'),
  66. ('F', 'Женский'),
  67. ]
  68. meloman_id = models.AutoField(primary_key=True)
  69. full_name = models.CharField(max_length=150)
  70. gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True, null=True)
  71. city = models.CharField(max_length=100, blank=True, null=True)
  72. birth_year = models.IntegerField(null=True, blank=True)
  73. user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name='meloman')
  74. class Meta:
  75. db_table = 'meloman'
  76. verbose_name = 'Меломан'
  77. verbose_name_plural = 'Меломанцы'
  78. def __str__(self):
  79. return self.full_name
  80. @property
  81. def age(self):
  82. """Расчетный атрибут: возраст меломана"""
  83. if not self.birth_year:
  84. return None
  85. return timezone.now().year - self.birth_year
  86. class Rating(models.Model):
  87. rating_id = models.AutoField(primary_key=True)
  88. meloman = models.ForeignKey(Meloman, on_delete=models.CASCADE, db_column='meloman_id')
  89. song = models.ForeignKey(Song, on_delete=models.CASCADE, db_column='song_id')
  90. score = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(10)])
  91. rating_date = models.DateField(auto_now_add=True)
  92. class Meta:
  93. db_table = 'rating'
  94. verbose_name = 'Оценка'
  95. verbose_name_plural = 'Оценки'
  96. unique_together = ['meloman', 'song'] # один меломан — одна оценка на песню
  97. def __str__(self):
  98. return f"{self.meloman.full_name} - {self.song.title}: {self.score}"
  99. class Preference(models.Model):
  100. preference_id = models.AutoField(primary_key=True)
  101. meloman = models.ForeignKey(Meloman, on_delete=models.CASCADE, db_column='meloman_id')
  102. genre = models.ForeignKey(Genre, on_delete=models.CASCADE, db_column='genre_id')
  103. class Meta:
  104. db_table = 'preference'
  105. verbose_name = 'Предпочтение'
  106. verbose_name_plural = 'Предпочтения'
  107. unique_together = ['meloman', 'genre']