Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Add file type information to the Django models #266

Merged
merged 5 commits into from
Oct 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion load_sample_data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ docker-compose exec -T "$UPSTREAM_DB_SERVICE_NAME" /bin/bash -c "psql -U deploy
docker-compose exec -T "$UPSTREAM_DB_SERVICE_NAME" /bin/bash -c "PGPASSWORD=deploy pg_dump -s -t audio -U deploy -d openledger -h db | head -n -14 | psql -U deploy -d openledger"
docker-compose exec -T "$UPSTREAM_DB_SERVICE_NAME" /bin/bash -c "psql -U deploy -d openledger <<-EOF
ALTER TABLE audio RENAME TO audio_view;
ALTER TABLE audio_view ADD COLUMN standardized_popularity double precision, ADD COLUMN ingestion_type varchar(1000), ADD column filetype varchar(80), ADD COLUMN audio_set jsonb;
ALTER TABLE audio_view ADD COLUMN standardized_popularity double precision, ADD COLUMN ingestion_type varchar(1000), ADD COLUMN audio_set jsonb;
\copy audio_view (identifier,created_on,updated_on,ingestion_type,provider,source,foreign_identifier,foreign_landing_url,url,thumbnail,filetype,duration,bit_rate,sample_rate,category,genres,audio_set,audio_set_position,alt_files,filesize,license,license_version,creator,creator_url,title,meta_data,tags,watermarked,last_synced_with_source,removed_from_source,standardized_popularity) from './sample_data/sample_audio_data.csv' with (FORMAT csv, HEADER true)
EOF"

Expand Down
43 changes: 43 additions & 0 deletions openverse_api/catalog/api/migrations/0038_filetypes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Generated by Django 3.2.7 on 2021-10-05 14:29

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0037_media_thumbnails'),
]

operations = [
migrations.AddField(
model_name='audio',
name='filetype',
field=models.CharField(blank=True, help_text='The type of the file, related to the file extension.', max_length=80, null=True),
),
migrations.AddField(
model_name='audioset',
name='filetype',
field=models.CharField(blank=True, help_text='The type of the file, related to the file extension.', max_length=80, null=True),
),
migrations.AddField(
model_name='image',
name='filetype',
field=models.CharField(blank=True, help_text='The type of the file, related to the file extension.', max_length=80, null=True),
),
migrations.AlterField(
model_name='audio',
name='filesize',
field=models.IntegerField(blank=True, help_text='Number in bytes, e.g. 1024.', null=True),
),
migrations.AlterField(
model_name='audioset',
name='filesize',
field=models.IntegerField(blank=True, help_text='Number in bytes, e.g. 1024.', null=True),
),
migrations.AlterField(
model_name='image',
name='filesize',
field=models.IntegerField(blank=True, help_text='Number in bytes, e.g. 1024.', null=True),
),
]
49 changes: 30 additions & 19 deletions openverse_api/catalog/api/models/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,36 @@ class AudioSet(IdentifierMixin, MediaMixin, FileMixin, OpenLedgerModel):
pass


class Audio(AbstractMedia):
class AudioFileMixin(FileMixin):
"""
This mixin adds fields related to audio quality to the standard file mixin.
Do not use this as the sole base class.
"""

bit_rate = models.IntegerField(
blank=True,
null=True,
help_text="Number in bits per second, eg. 128000.",
)
sample_rate = models.IntegerField(
blank=True,
null=True,
help_text="Number in hertz, eg. 44100.",
)

@property
def sample_rate_in_khz(self):
return self.sample_rate / 1e3

@property
def bit_rate_in_kbps(self):
return self.bit_rate / 1e3

class Meta:
abstract = True


class Audio(AudioFileMixin, AbstractMedia):
audio_set = models.ForeignKey(
help_text="Reference to set of which this track is a part.",
to=AudioSet,
Expand Down Expand Up @@ -85,16 +114,6 @@ class Audio(AbstractMedia):
null=True,
help_text="The time length of the audio file in milliseconds.",
)
bit_rate = models.IntegerField(
blank=True,
null=True,
help_text="Number in bits per second, eg. 128000.",
)
sample_rate = models.IntegerField(
blank=True,
null=True,
help_text="Number in hertz, eg. 44100.",
)

alt_files = models.JSONField(
blank=True,
Expand All @@ -112,14 +131,6 @@ def alternative_files(self):
def duration_in_s(self):
return self.duration / 1e3

@property
def sample_rate_in_khz(self):
return self.sample_rate / 1e3

@property
def bit_rate_in_kbps(self):
return self.bit_rate / 1e3

class Meta(AbstractMedia.Meta):
db_table = "audio"

Expand Down
19 changes: 18 additions & 1 deletion openverse_api/catalog/api/models/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,31 @@
AbstractMediaList,
AbstractMediaReport,
)
from catalog.api.models.mixins import FileMixin
from django.db import models
from uuslug import uuslug


class Image(AbstractMedia):
class ImageFileMixin(FileMixin):
"""
This mixin adds fields related to image resolution to the standard file
mixin. Do not use this as the sole base class.
"""

width = models.IntegerField(blank=True, null=True)
height = models.IntegerField(blank=True, null=True)

@property
def resolution_in_mp(self): # ~ MP or megapixels
return (self.width * self.height) / 1e6

class Meta:
abstract = True


class Image(ImageFileMixin, AbstractMedia):
pass
dhruvkb marked this conversation as resolved.
Show resolved Hide resolved

class Meta(AbstractMedia.Meta):
db_table = "image"

Expand Down
27 changes: 24 additions & 3 deletions openverse_api/catalog/api/models/media.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import mimetypes

import catalog.api.controllers.search_controller as search_controller
from catalog.api.licenses import ATTRIBUTION, get_license_url
from catalog.api.models.base import OpenLedgerModel
from catalog.api.models.mixins import FileMixin, IdentifierMixin, MediaMixin
from catalog.api.models.mixins import IdentifierMixin, MediaMixin
from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.utils.html import format_html
Expand All @@ -17,7 +19,7 @@
OTHER = "other"


class AbstractMedia(IdentifierMixin, MediaMixin, FileMixin, OpenLedgerModel):
class AbstractMedia(IdentifierMixin, MediaMixin, OpenLedgerModel):
"""
Generic model from which to inherit all media classes. This class stores
information common to all media types indexed by Openverse.
Expand Down Expand Up @@ -259,9 +261,28 @@ class AbstractAltFile:
provides alternative qualities, formats and resolutions that are available
from the provider that are not canonical.

The schema of the class must correspond to that of the ``FileMixin`` class.
The schema of the class must correspond to that of the
:py:class:`catalog.api.models.mixins.FileMixin` class.
"""

def __init__(self, attrs):
self.url = attrs.get("url")
self.filesize = attrs.get("filesize")
self.filetype = attrs.get("filetype")

@property
def size_in_mib(self): # ~ MiB or mibibytes
return self.filesize / 2 ** 20

@property
def size_in_mb(self): # ~ MB or megabytes
return self.filesize / 1e6

@property
def mime_type(self):
"""
Get the MIME type of the file inferred from the extension of the file.
:return: the inferred MIME type of the file
"""

return mimetypes.types_map[f".{self.filetype}"]
32 changes: 31 additions & 1 deletion openverse_api/catalog/api/models/mixins.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import mimetypes

from django.db import models


Expand Down Expand Up @@ -64,7 +66,35 @@ class FileMixin(models.Model):
url = models.URLField(
unique=True, max_length=1000, help_text="The actual URL to the media file."
)
filesize = models.IntegerField(blank=True, null=True)
filesize = models.IntegerField(
blank=True,
null=True,
help_text="Number in bytes, e.g. 1024.",
# Bytes for parity with the HTTP Content-Length header
dhruvkb marked this conversation as resolved.
Show resolved Hide resolved
)
filetype = models.CharField(
max_length=80,
blank=True,
null=True,
help_text="The type of the file, related to the file extension.",
)

@property
def size_in_mib(self): # ~ MiB or mibibytes
return self.filesize / 2 ** 20

@property
def size_in_mbs(self): # ~ MB or megabytes
return self.filesize / 1e6

@property
def mime_type(self):
"""
Get the MIME type of the file inferred from the extension of the file.
:return: the inferred MIME type of the file
"""

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

class Meta:
abstract = True