Let's create a music app that we'll be using throughout this chapter:
- Create the music app itself and put it under INSTALLED_APPS in the settings:
# myproject/settings/_base.py
INSTALLED_APPS = [
# …
"myproject.apps.core",
"myproject.apps.music",
]
- The Song model there should contain the uuid, artist, title, url, and image fields. We'll also extend CreationModificationDateBase to add creation and modification timestamps, as well as UrlBase to add methods to work with the model's detail URLs:
# myproject/apps/music/models.py
import os
import uuid
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.db import models
from django.utils.text import slugify
from myproject.apps.core.models import CreationModificationDateBase, UrlBase
def upload_to(instance, filename):
filename_base, filename_ext = os.path.splitext(filename)
artist = slugify(instance.artist)
title = slugify(instance.title)
return f"music/{artist}--{title}{filename_ext.lower()}"
class Song(CreationModificationDateBase, UrlBase):
uuid = models.UUIDField(primary_key=True, default=None,
editable=False)
artist = models.CharField(_("Artist"), max_length=250)
title = models.CharField(_("Title"), max_length=250)
url = models.URLField(_("URL"), blank=True)
image = models.ImageField(_("Image"), upload_to=upload_to,
blank=True, null=True)
class Meta:
verbose_name = _("Song")
verbose_name_plural = _("Songs")
unique_together = ["artist", "title"]
def __str__(self):
return f"{self.artist} - {self.title}"
def get_url_path(self):
return reverse("music:song_detail", kwargs={"pk": self.pk})
def save(self, *args, **kwargs):
if self.pk is None:
self.pk = uuid.uuid4()
super().save(*args, **kwargs)
- Make and run migrations with the following commands:
(env)$ python manage.py makemigrations
(env)$ python manage.py migrate
- Then, let's add a simple administration for the Song model:
# myproject/apps/music/admin.py
from django.contrib import admin
from .models import Song
@admin.register(Song)
class SongAdmin(admin.ModelAdmin):
list_display = ["title", "artist", "url"]
list_filter = ["artist"]
search_fields = ["title", "artist"]
- Also, we need a form for validating and creating Song models in the import scripts. It's the most straightforward model form, as follows:
# myproject/apps/music/forms.py
from django import forms
from django.utils.translation import ugettext_lazy as _
from .models import Song
class SongForm(forms.ModelForm):
class Meta:
model = Song
fields = "__all__"