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

1import mimetypes 

2 

3from django.db import models 

4 

5 

6class IdentifierMixin(models.Model): 

7 """ 

8 This mixin adds fields related to unique ID, both internal and external, to a model. 

9 

10 Do not use this as the sole base class. 

11 

12 The mixins adds 

13 

14 - identifier: UUIDField 

15 """ 

16 

17 identifier = models.UUIDField( 

18 unique=True, 

19 db_index=True, 

20 help_text="Our unique identifier for an open-licensed work.", 

21 ) 

22 

23 class Meta: 

24 abstract = True 

25 

26 

27class ForeignIdentifierMixin(models.Model): 

28 """ 

29 This mixin adds fields related to the external unique ID to any model. 

30 

31 Do not use this as the sole base class. 

32 

33 This mixin adds 

34 

35 - foreign_identifier: TextField 

36 """ 

37 

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 ) 

44 

45 class Meta: 

46 abstract = True 

47 

48 

49class MediaMixin(models.Model): 

50 """ 

51 This mixin adds fields related to a creation such as the title and artist info. 

52 

53 Do not use this as the sole base class. 

54 

55 The mixin adds 

56 

57 - title: TextField 

58 - foreign_landing_url: TextField 

59 - creator: TextField 

60 - creator_url: TextField 

61 - thumbnail: TextField 

62 - provider: CharField 

63 """ 

64 

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 ) 

76 

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 ) 

89 

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 ) 

98 

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 ) 

107 

108 class Meta: 

109 abstract = True 

110 

111 

112class FileMixin(models.Model): 

113 """ 

114 This mixin adds fields related to file such as the file URL and size to any model. 

115 

116 Do not use this as the sole base class. 

117 

118 This mixin adds 

119 

120 - url: TextField 

121 - filesize: IntegerField 

122 - filetype: CharField 

123 """ 

124 

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 ) 

145 

146 @property 

147 def size_in_mib(self): # ~ MiB or mibibytes 

148 return self.filesize / 2**20 

149 

150 @property 

151 def size_in_mbs(self): # ~ MB or megabytes 

152 return self.filesize / 1e6 

153 

154 @property 

155 def mime_type(self): 

156 """ 

157 Get the MIME type of the file inferred from the extension of the file. 

158 

159 :return: the inferred MIME type of the file 

160 """ 

161 

162 return mimetypes.types_map[f".{self.filetype}"] 

163 

164 class Meta: 

165 abstract = True