---
# System prepended metadata

title: Django Models
tags: [mobile-development, backend]

---

# Django Models
###### tags: `mobile-development` `backend`

When we say a model in django, it simply means a `table` in the database.

So to define our database tables in django, we simply create a `Model` for each table. Django models itself has tons of varietyand you should defeinitely check out their documentation at [This link first](https://docs.djangoproject.com/en/4.1/topics/db/models/) and then go to see the different types of fields in [Here](https://docs.djangoproject.com/en/4.1/ref/models/fields/#model-field-types).

We will be building a very simple (not perfectly designed to avoid difficulties for students with less experience) movies app, where people can see movies (or series) details, news, trailers and actors.

Here is the code for the models: 
```python=
from django.core.validators import MinValueValidator
from django.db import models
import uuid


class Category(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True, null=False, db_column='created_at')
    updated = models.DateTimeField(auto_now=True, null=False, db_column='updated_at')
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name


class Movie(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True, null=False, db_column='created_at')
    updated = models.DateTimeField(auto_now=True, null=False, db_column='updated_at')
    title = models.CharField(max_length=150)
    release_date = models.DateField(db_column='date')
    description = models.TextField()
    rating = models.DecimalField(max_digits=2, decimal_places=1)
    is_for_adults = models.BooleanField(default=False)
    trailer_url = models.URLField(null=True, blank=True)
    is_featured = models.BooleanField(default=False)
    length = models.CharField(max_length=6)
    categories = models.ManyToManyField(Category, related_name='movies', blank=True)
    image = models.URLField(null=True, blank=True)
    thumbnail = models.URLField(null=True, editable=False)

    def __str__(self):
        return self.title

    @property
    def actors(self):
        return self.actors.all()


class Serial(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True, null=False, db_column='created_at')
    updated = models.DateTimeField(auto_now=True, null=False, db_column='updated_at')
    title = models.CharField(max_length=150)
    release_date = models.DateField(db_column='date')
    description = models.TextField()
    rating = models.DecimalField(max_digits=2, decimal_places=1)
    is_for_adults = models.BooleanField(default=False)
    trailer_url = models.URLField(null=True, blank=True)
    is_featured = models.BooleanField(default=False)
    categories = models.ManyToManyField(Category, related_name='series')
    image = models.URLField(null=True)
    thumbnail = models.URLField(null=True, editable=False)

    def __str__(self):
        return self.title

    @property
    def actors(self):
        return self.actors.all()

    @property
    def seasons(self):
        return self.seasons.all()


class Season(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True, null=False, db_column='created_at')
    updated = models.DateTimeField(auto_now=True, null=False, db_column='updated_at')
    number = models.PositiveIntegerField(
        validators=[MinValueValidator(1, message='Minimum season for any series is 1')])
    serial = models.ForeignKey(Serial, on_delete=models.CASCADE, related_name='seasons')

    def __str__(self):
        return f'{self.serial.title} || Season {self.number}'


class Episode(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True, null=False, db_column='created_at')
    updated = models.DateTimeField(auto_now=True, null=False, db_column='updated_at')
    title = models.CharField(max_length=150)
    release_date = models.DateField(db_column='date')
    description = models.TextField()
    rating = models.DecimalField(max_digits=2, decimal_places=1)
    is_for_adults = models.BooleanField(default=False)
    trailer_url = models.URLField(null=True, blank=True)
    number = models.PositiveIntegerField(
        validators=[MinValueValidator(1, message='Minimum season for any episode is 1')])
    season = models.ForeignKey(Season, on_delete=models.CASCADE, related_name='episodes')
    length = models.CharField(max_length=6)

    def __str__(self):
        return f'{self.season} || {self.title}'

    @property
    def actors(self):
        return self.season.serial.actors.all() + self.actors.all()

    @property
    def image(self):
        return self.season.serial.image


class New(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True, null=False, db_column='created_at')
    updated = models.DateTimeField(auto_now=True, null=False, db_column='updated_at')
    title = models.CharField(max_length=255)
    description = models.TextField()
    date = models.DateField(db_column='date')
    image = models.URLField(unique=True, null=True)

    def __str__(self):
        return self.title


class Actor(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True, null=False, db_column='created_at')
    updated = models.DateTimeField(auto_now=True, null=False, db_column='updated_at')
    name = models.CharField(max_length=50)
    image = models.URLField(null=True)
    movies = models.ManyToManyField(Movie, related_name='actors', blank=True)
    series = models.ManyToManyField(Serial, related_name='actors', blank=True)
    episodes = models.ManyToManyField(Episode, related_name='guest_actors', blank=True)

```
----

## Refactoring
----
We can refactor a little bit from the above code to make it a bit more succinct, as follows: 
```python=
from django.core.validators import MinValueValidator
from django.db import models
import uuid


class Entity(models.Model):
    class Meta:
        abstract = True

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created = models.DateTimeField(auto_now_add=True, null=False, db_column='created_at')
    updated = models.DateTimeField(auto_now=True, null=False, db_column='updated_at')


class Category(Entity):
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name


class CommonDetail(Entity):
    class Meta:
        abstract = True

    title = models.CharField(max_length=150)
    release_date = models.DateField(db_column='date')
    description = models.TextField()
    rating = models.DecimalField(max_digits=2, decimal_places=1)
    is_for_adults = models.BooleanField(default=False)
    trailer_url = models.URLField(null=True, blank=True)


class Movie(CommonDetail):
    is_featured = models.BooleanField(default=False)
    length = models.CharField(max_length=6)
    categories = models.ManyToManyField(Category, related_name='movies')
    image = models.URLField(null=True)
    thumbnail = models.URLField(null=True, editable=False)

    def __str__(self):
        return self.title

    @property
    def actors(self):
        return self.actors.all()


class Serial(CommonDetail):
    is_featured = models.BooleanField(default=False)
    categories = models.ManyToManyField(Category, related_name='series')
    image = models.URLField(null=True)
    thumbnail = models.URLField(null=True, editable=False)

    def __str__(self):
        return self.title

    @property
    def actors(self):
        return self.actors.all()

    @property
    def seasons(self):
        return self.seasons.all()


class Season(Entity):
    number = models.PositiveIntegerField(
        validators=[MinValueValidator(1, message='Minimum season for any series is 1')])
    serial = models.ForeignKey(Serial, on_delete=models.CASCADE, related_name='seasons')

    def __str__(self):
        return f'{self.serial.title} || Season {self.number}'


class Episode(CommonDetail):
    number = models.PositiveIntegerField(
        validators=[MinValueValidator(1, message='Minimum season for any episode is 1')])
    season = models.ForeignKey(Season, on_delete=models.CASCADE, related_name='episodes')
    length = models.CharField(max_length=6)

    def __str__(self):
        return f'{self.season} || {self.title}'

    @property
    def actors(self):
        return self.season.serial.actors.all() + self.actors.all()

    @property
    def image(self):
        return self.season.serial.image


class New(Entity):
    title = models.CharField(max_length=255)
    description = models.TextField()
    date = models.DateField(db_column='date')
    image = models.URLField(unique=True, null=True)

    def __str__(self):
        return self.title


class Actor(Entity):
    name = models.CharField(max_length=50)
    image = models.URLField(null=True)
    movies = models.ManyToManyField(Movie, related_name='actors', blank=True)
    series = models.ManyToManyField(Serial, related_name='actors', blank=True)
    episodes = models.ManyToManyField(Episode, related_name='guest_actors', blank=True)

```