Tag

All primary entities but the genre and URL (i.e. area, artist, event, instrument, label, place, recording, release, release group, series and work) have *_tag and *_tag_raw tables, with the same structure. These tables contain two foreign keys, linked to the associated entity and to the tag table. The *_tag_raw tables contain a foreign key, editor, which specifies who added the tag, while the *_tag tables instead contain a count of how many times a tag is applied to a particular entity, and a last_updated timestamp. For privacy reasons, the *_tag_raw tables aren’t included in the database dumps. The tag table contains the actual names of the tags, and a ref_count indicating how often the tag has been used.

Model Documentation

class django_musicbrainz_connector.models.tag.Tag(*args, **kwargs)[source]

PostgreSQL Definition

The tag table is defined in the MusicBrainz Server as:

CREATE TABLE tag ( -- replicate (verbose)
    id                  SERIAL,
    name                VARCHAR(255) NOT NULL,
    ref_count           INTEGER NOT NULL DEFAULT 0
);
class django_musicbrainz_connector.models.base_tag_model.TagModel(*args, **kwargs)[source]

PostgreSQL Definition

The M_tag table is defined in the MusicBrainz Server as:

CREATE TABLE M_tag ( -- replicate (verbose)
    M                   INTEGER NOT NULL, -- PK, references M.id
    tag                 INTEGER NOT NULL, -- PK, references tag.id
    count               INTEGER NOT NULL,
    last_updated        TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

Model Source

Tag

class Tag(models.Model):
    """
    PostgreSQL Definition
    ---------------------

    The :code:`tag` table is defined in the MusicBrainz Server as:

    .. code-block:: sql

        CREATE TABLE tag ( -- replicate (verbose)
            id                  SERIAL,
            name                VARCHAR(255) NOT NULL,
            ref_count           INTEGER NOT NULL DEFAULT 0
        );

    """

    id = models.IntegerField("ID", primary_key=True, db_column="id")
    name = models.CharField(max_length=255, db_column="name")
    ref_count = models.IntegerField("Ref Count", db_column="ref_count")

    def __str__(self) -> str:
        return self.name

    class Meta:
        managed = False
        db_table = "tag"
        verbose_name_plural = "Tags"
        ordering = ["name"]

TagModel

class TagModel(models.Model):
    """
    PostgreSQL Definition
    ---------------------

    The :code:`M_tag` table is defined in the MusicBrainz Server as:

    .. code-block:: sql

        CREATE TABLE M_tag ( -- replicate (verbose)
            M                   INTEGER NOT NULL, -- PK, references M.id
            tag                 INTEGER NOT NULL, -- PK, references tag.id
            count               INTEGER NOT NULL,
            last_updated        TIMESTAMP WITH TIME ZONE DEFAULT NOW()
        );

    """

    tag = models.ForeignKey("Tag", db_column="tag", on_delete=models.PROTECT)
    count = models.IntegerField("Count", db_column="count")
    last_updated = models.DateTimeField(db_column="last_updated")

    class Meta:
        abstract = True

Dynamic model creation for tagged table

from django.apps import AppConfig
from django.db import models

from django_musicbrainz_connector.utils import clone_field


class DjangoMusicbrainzConnectorConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "django_musicbrainz_connector"

    def ready(self):

        # Also available, but not in django_musicbrainz_connector yet: Event, Instrument, Label, Place, Series
        import django_musicbrainz_connector.models
        from django_musicbrainz_connector.models import Area, Artist, Recording, Release, ReleaseGroup, Tag, Work
        from django_musicbrainz_connector.models.base_tag_model import TagModel

        for model_class in [Area, Artist, Recording, Release, ReleaseGroup, Work]:
            # Creation of the <Model>Tag model, based on the list
            class_name = f"{model_class.__qualname__}Tag"
            class_relation_name = model_class._meta.db_table

            # Create the Meta class (not metaclass) for the <Model>Tag class
            meta_class = type(
                "Meta",
                (),
                {
                    "managed": False,
                    "db_table": f"{class_relation_name}_tag",
                    "verbose_name_plural": f"{model_class.__qualname__} Tags",
                    "ordering": ["pk"],
                },
            )

            tag_field = TagModel._meta.get_field("tag")

            model_tag_class = type(
                class_name,
                (TagModel,),
                {
                    "__module__": "django_musicbrainz_connector.models",
                    # All `M_tag` table have composite primary key with the `M` table and the tag one
                    "pk": models.CompositePrimaryKey(class_relation_name, "tag"),
                    class_relation_name: models.ForeignKey(
                        model_class,
                        on_delete=models.PROTECT,
                        db_column=class_relation_name,
                        # Access through `M.m_tag_m2m.all()`
                        related_name=f"{class_relation_name}_tag_m2m",
                    ),
                    # Access through `tag.m_tag_m2m.all()`
                    "tag": clone_field(tag_field, related_name=f"{class_relation_name}_tag_m2m"),
                    "Meta": meta_class,
                },
            )
            # Set into the module so it can be auto imported
            # with `from django_musicbrainz_connector.models import ModelTag`
            setattr(django_musicbrainz_connector.models, class_name, model_tag_class)

            # Add the m2m relation between Model <> Tag, so we can use:
            # - the convenient `tag.models.all()`
            # - and `model.tags.all()`
            # Without the necessity of manually navigating the through-table,
            # those options remain accessible through:
            # - `model.model_tag_m2m.all()`
            # - and the reverse: `tag.model_tag_m2m.all()`
            Tag.add_to_class(
                f"{class_relation_name}s",
                models.ManyToManyField(model_class, through=model_tag_class, related_name="tags"),
            )