models.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. from enum import Enum
  2. from django.conf import settings
  3. from django.core.validators import MaxValueValidator, MinValueValidator
  4. from django.db import models
  5. from django.urls import reverse
  6. from django_extensions.db.models import TimeStampedModel
  7. from django_extensions.db.fields import AutoSlugField
  8. from emus.utils import ChoiceEnum
  9. def get_screenshot_upload_path(instance, filename):
  10. return f"{instance.game_system.retropie_slug}/screenshots/{filename}"
  11. def get_marquee_upload_path(instance, filename):
  12. return f"{instance.game_system.retropie_slug}/marquee/{filename}"
  13. def get_video_upload_path(instance, filename):
  14. return f"{instance.game_system.retropie_slug}/videos/{filename}"
  15. def get_rom_upload_path(instance, filename):
  16. return f"{instance.game_system.retropie_slug}/{filename}"
  17. class Region(Enum):
  18. USA = "US"
  19. EUROPE = "EU"
  20. JAPAN = "JP"
  21. class BaseModel(TimeStampedModel):
  22. """A base model for providing name and slugged fields for organizational models"""
  23. name = models.CharField(max_length=255)
  24. slug = AutoSlugField(populate_from="name")
  25. class Meta:
  26. ordering = ["name"]
  27. abstract = True
  28. def slugify_function(self, content):
  29. for element in settings.REMOVE_FROM_SLUGS:
  30. content = content.replace(element, "-")
  31. return content.lower()
  32. def __str__(self):
  33. return self.name
  34. class Genre(BaseModel):
  35. def get_absolute_url(self):
  36. return reverse("games:genre_detail", args=[self.slug])
  37. class Publisher(BaseModel):
  38. def get_absolute_url(self):
  39. return reverse("games:publisher_detail", args=[self.slug])
  40. class Developer(BaseModel):
  41. def get_absolute_url(self):
  42. return reverse("games:developer_detail", args=[self.slug])
  43. class GameSystem(BaseModel):
  44. retropie_slug = models.CharField(
  45. blank=True,
  46. null=True,
  47. max_length=50,
  48. )
  49. color = models.CharField(
  50. blank=True,
  51. null=True,
  52. max_length=6,
  53. help_text="Hex value for console badges",
  54. )
  55. @property
  56. def defaults(self):
  57. return settings.GAME_SYSTEM_DEFAULTS.get(self.retropie_slug, None)
  58. @property
  59. def get_color(self):
  60. color = self.color
  61. if not color and self.defaults:
  62. color = self.defaults.get("color", "")
  63. return color
  64. @property
  65. def webretro_core(self):
  66. core = None
  67. if self.defaults:
  68. core = self.defaults.get("webretro_core", None)
  69. return core
  70. def get_absolute_url(self):
  71. return reverse("games:game_system_detail", args=[self.slug])
  72. class Game(BaseModel):
  73. class Region(ChoiceEnum):
  74. US = "USA"
  75. EU = "Europe"
  76. JP = "Japan"
  77. X = "Unknown"
  78. game_system = models.ForeignKey(
  79. GameSystem,
  80. on_delete=models.SET_NULL,
  81. null=True,
  82. )
  83. release_date = models.DateField(
  84. blank=True,
  85. null=True,
  86. )
  87. developer = models.ForeignKey(
  88. Developer,
  89. on_delete=models.SET_NULL,
  90. blank=True,
  91. null=True,
  92. )
  93. publisher = models.ForeignKey(
  94. Publisher,
  95. on_delete=models.SET_NULL,
  96. blank=True,
  97. null=True,
  98. )
  99. genre = models.ManyToManyField(
  100. Genre,
  101. )
  102. players = models.SmallIntegerField(
  103. default=1,
  104. )
  105. kid_game = models.BooleanField(
  106. default=False,
  107. )
  108. description = models.TextField(
  109. blank=True,
  110. null=True,
  111. )
  112. rating = models.FloatField(
  113. blank=True,
  114. null=True,
  115. validators=[MaxValueValidator(1), MinValueValidator(0)],
  116. )
  117. video = models.FileField(
  118. blank=True,
  119. null=True,
  120. max_length=300,
  121. upload_to=get_video_upload_path,
  122. )
  123. marquee = models.ImageField(
  124. blank=True,
  125. null=True,
  126. max_length=300,
  127. upload_to=get_marquee_upload_path,
  128. )
  129. screenshot = models.ImageField(
  130. blank=True,
  131. null=True,
  132. max_length=300,
  133. upload_to=get_screenshot_upload_path,
  134. )
  135. rom_file = models.FileField(
  136. blank=True,
  137. null=True,
  138. max_length=300,
  139. upload_to=get_rom_upload_path,
  140. )
  141. hack = models.BooleanField(
  142. default=False,
  143. )
  144. hack_version = models.CharField(
  145. max_length=255,
  146. blank=True,
  147. null=True,
  148. )
  149. english_patched = models.BooleanField(
  150. default=False,
  151. )
  152. english_patched_version = models.CharField(
  153. max_length=50,
  154. blank=True,
  155. null=True,
  156. )
  157. undub = models.BooleanField(
  158. default=False,
  159. )
  160. featured = models.BooleanField(
  161. default=False,
  162. )
  163. region = models.CharField(
  164. max_length=10,
  165. choices=Region.choices(),
  166. blank=True,
  167. null=True,
  168. )
  169. class Meta:
  170. ordering = ["game_system", "name"]
  171. def __str__(self):
  172. return f"{self.name} for {self.game_system}"
  173. def rating_by_100(self) -> float:
  174. if self.rating:
  175. return int(100 * self.rating)
  176. return int(0)
  177. def get_absolute_url(self):
  178. return reverse("games:game_detail", args=[self.slug])
  179. def get_play_url(self):
  180. if "webretro_core" in self.game_system.defaults.keys():
  181. return reverse("games:game_play_detail", args=[self.slug])