How can I create an "Artist" instance from my Django model when an instance of a User class is created?

52 views Asked by At

I am building a web API in Django and DRF. I have an Artist model that contains different fields and a OneToOnefield to a user which was inherited from an AbstractBaseUser class that contains the following fields: username, email, first_name, last_name, is_artist. I want a situation whereby once a user is created, an instance of the Artist model is also created.

Note: I am handling authentication endpoints using Third-Party packages and libraries using Djoser. So I didn't define any views for the user model.

How can I achieve what I have described above?

Here's my code:

The User model:

import uuid

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from .managers import CustomUserManager


class User(AbstractBaseUser, PermissionsMixin):
    pkid = models.BigAutoField(primary_key=True, editable=False)
    id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    username = models.CharField(verbose_name=_("Username"), max_length=255, unique=True)
    first_name = models.CharField(verbose_name=_("First Name"), max_length=50)
    last_name = models.CharField(verbose_name=_("Last Name"), max_length=50)
    email = models.EmailField(verbose_name=_("Email Address"), unique=True)
    is_artist = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(default=timezone.now)

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["username", "first_name", "last_name", "is_artist"]

    objects = CustomUserManager()

    class Meta:
        verbose_name = _("User")
        verbose_name_plural = _("Users")

    def __str__(self):
        return self.username

    @property
    def get_full_name(self):
        return f"{self.first_name} {self.last_name}"

    def get_short_name(self):
        return self.username

The Artist model:

from django.contrib.auth import get_user_model
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_countries.fields import CountryField
from phonenumber_field.modelfields import PhoneNumberField

from common.models import TimeStampedUUIDModel


User = get_user_model()


class Gender(models.TextChoices):
    MALE = "Male", _("Male")
    FEMALE = "Female", _("Female")
    OTHER = "Other", _("Other")


class Artist(TimeStampedUUIDModel):
    user = models.OneToOneField(User, related_name="artist", on_delete=models.CASCADE)
    stage_name = models.CharField(verbose_name=_("Stage Name"), max_length=255, unique=True)
    gender = models.CharField(verbose_name=_("Gender"), choices=Gender.choices, default=Gender.OTHER, max_length=20)
    phone_number = PhoneNumberField(verbose_name=_("Phone Number"), max_length=30, default="+2348037286666", unique=True)
    bio = models.CharField(verbose_name=_("Bio"), max_length=255, blank=True, null=True)
    music_class = models.CharField(verbose_name=_("Music Class"), max_length=255, blank=True)
    company_name = models.CharField(verbose_name=_("Company Name"), max_length=55, blank=True)
    sor = models.CharField(verbose_name=_("State of Residence"), max_length=255, blank=True)
    lga = models.CharField(verbose_name=_("Local Government Area"), max_length=225, blank=True, null=True)
    address = models.CharField(verbose_name=_("Address"), blank=True, max_length=225)
    postal_code = models.CharField(verbose_name=_("Postal Code"), blank=True, null=True, max_length=8)
    country = CountryField(verbose_name=_("Country"), default="NG", blank=True, null=True)
    country_code = models.CharField(verbose_name=_('Country Code'), default="NG", blank=True, max_length=5) 
    state = models.CharField(verbose_name=_("State"), max_length=25, null=True, blank=True) 
    city = models.CharField(verbose_name=_("city"), max_length=75, null=True, blank=True) 
    dob = models.DateField(verbose_name=_("Date of Birth"), null=True)
    
    
    def __str__(self):
        return f"{self.user.username}'s profile"
1

There are 1 answers

4
SamSparx On

The simplest way is to extend the save function of your User

class User(
    ...
    def save(self, *args, **kwargs):
        #first we test to see if object has an ID -if not, it's newly created
        created = self.pk is None
        #call the super function so it performs the normal save() process
        super().save(*args, **kwargs)
        #now, for new objects, we also create an artist
        if created and self.is_artist:
            Artist.objects.create(user = self, ...