Coverage for api/models/mixins.py: 91%
34 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 06:14 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 06:14 +0000
1import mimetypes
3from django.db import models
6class IdentifierMixin(models.Model):
7 """
8 This mixin adds fields related to unique ID, both internal and external, to a model.
10 Do not use this as the sole base class.
12 The mixins adds
14 - identifier: UUIDField
15 """
17 identifier = models.UUIDField(
18 unique=True,
19 db_index=True,
20 help_text="Our unique identifier for an open-licensed work.",
21 )
23 class Meta:
24 abstract = True
27class ForeignIdentifierMixin(models.Model):
28 """
29 This mixin adds fields related to the external unique ID to any model.
31 Do not use this as the sole base class.
33 This mixin adds
35 - foreign_identifier: TextField
36 """
38 foreign_identifier = models.TextField(
39 blank=True,
40 null=True,
41 db_index=True,
42 help_text="The identifier provided by the upstream source.",
43 )
45 class Meta:
46 abstract = True
49class MediaMixin(models.Model):
50 """
51 This mixin adds fields related to a creation such as the title and artist info.
53 Do not use this as the sole base class.
55 The mixin adds
57 - title: TextField
58 - foreign_landing_url: TextField
59 - creator: TextField
60 - creator_url: TextField
61 - thumbnail: TextField
62 - provider: CharField
63 """
65 title = models.TextField(
66 blank=True,
67 null=True,
68 help_text="The name of the media.",
69 )
70 foreign_landing_url = models.TextField(
71 blank=True,
72 null=True,
73 verbose_name="foreign landing URL",
74 help_text="The landing page of the work.",
75 )
77 creator = models.TextField(
78 blank=True,
79 null=True,
80 help_text="The name of the media creator.",
81 )
82 creator_url = models.TextField(
83 max_length=2000,
84 blank=True,
85 null=True,
86 verbose_name="creator URL",
87 help_text="A direct link to the media creator.",
88 )
90 # Because all forms of media have a thumbnail for visual representation
91 # For images, this field is not used as images are generated using Photon.
92 # For audio, this field points to the artwork, or is ``null``.
93 thumbnail = models.TextField(
94 blank=True,
95 null=True,
96 help_text="The thumbnail for the media.",
97 )
99 # This is different from ``source`` (see ``AbstractMedia``)
100 provider = models.CharField(
101 max_length=80,
102 blank=True,
103 null=True,
104 db_index=True,
105 help_text="The content provider, e.g. Flickr, Jamendo...",
106 )
108 class Meta:
109 abstract = True
112class FileMixin(models.Model):
113 """
114 This mixin adds fields related to file such as the file URL and size to any model.
116 Do not use this as the sole base class.
118 This mixin adds
120 - url: TextField
121 - filesize: IntegerField
122 - filetype: CharField
123 """
125 url = models.TextField(
126 unique=True,
127 max_length=1000,
128 blank=True,
129 null=True,
130 verbose_name="URL",
131 help_text="The actual URL to the media file.",
132 )
133 filesize = models.IntegerField(
134 blank=True,
135 null=True,
136 help_text="Number in bytes, e.g. 1024.",
137 # Bytes for parity with the HTTP Content-Length header
138 )
139 filetype = models.CharField(
140 max_length=80,
141 blank=True,
142 null=True,
143 help_text="The type of the file, related to the file extension.",
144 )
146 @property
147 def size_in_mib(self): # ~ MiB or mibibytes
148 return self.filesize / 2**20
150 @property
151 def size_in_mbs(self): # ~ MB or megabytes
152 return self.filesize / 1e6
154 @property
155 def mime_type(self):
156 """
157 Get the MIME type of the file inferred from the extension of the file.
159 :return: the inferred MIME type of the file
160 """
162 return mimetypes.types_map[f".{self.filetype}"]
164 class Meta:
165 abstract = True