Unlocking the Magic of Data: An Introduction to Django Models

Ukeme Wilson
6 min readJun 28, 2024

--

Imagine a world where your web applications can seamlessly manage and interact with databases without breaking a sweat. Welcome to the realm of Django Models, where the power of Python meets the elegance of streamlined data management.

A model is a Python class that represents a table in the database.

It is a definitive source of information about your data. It contains the essential fields and behaviors of the data you are storing. Generally, each model maps to a single database table.

Django models provide simplicity, consistency, version control, and advanced metadata handling.

To define a model, you create a class that inherits from django.db.models.Model.

Fields

A model can have an arbitrary number of fields, of any type — each one represents a column of data(database field) that we want to store in one of our database tables.

Lets consider this example.

class Book(models.Model):
title = models.CharField(max_length=50)
pages = models.IntegerField()
best_seller = models.BooleanField(default=True)
cover_picture = models.ImageField()
summary = models.TextField()
price = models.FloatField()
created_at = models.DateTimeField()

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

We have created a model called Book. That is like creating a database table called Book. In this book table, we have specified several columns. Lets examine them

CharField:

This is a used for storing short-to-medium sized strings in a model. Typically maps to a VARCHAR column in the database.

Parameters:

max_length: Specifies the maximum length of the string. This parameter is required.

IntergerField:

This is suitable for storing numeric data where only whole numbers are required, such as counting items, representing IDs, or storing quantities. Typically maps to an INTEGER column in the database

BooleanField:

This is suitable for storing data that has only two possible states, such as flags, status indicators, or any binary choice. is a field used to store boolean values (True or False). Typically maps to a BOOLEAN or TINYINT(1) column in the database.

ImageField:

This is used to store image files in a model. Typically maps to a VARCHAR column in the database that stores the file path.

Parameters:

upload_to: Specifies the directory within the MEDIA_ROOT where files will be uploaded.

height_field: Optionally stores the height of the image.

width_field: Optionally stores the width of the image.

TextField:

This is used to store large text data in a model. Typically maps to a TEXT column in the database.

FloatField:

This is used to store floating-point numbers in a model. Typically maps to a FLOAT column in the database.

DateTimeField:

This is used to store date and time information in a model. Typically maps to a DATETIME

Parameters:

auto_now: If True, the field is automatically set to the current date and time every time the object is saved.

auto_now_add: If True, the field is automatically set to the current date and time when the object is first created.

EmailField:

This is used to store and validate email addresses.

Other fields include:

"AutoField"
"BLANK_CHOICE_DASH"
"BigAutoField"
"BigIntegerField"
"BinaryField"
"CommaSeparatedIntegerField"
"DateField"
"DurationField"
"FilePathField"
"GenericIPAddressField"
"IPAddressField"
"NOT_PROVIDED"
"NullBooleanField"
"PositiveBigIntegerField"
"PositiveIntegerField"
"PositiveSmallIntegerField"
"SlugField"
"SmallAutoField"
"SmallIntegerField"
"TimeField"
"URLField"
"UUIDField"

Common Field Arguments (Optional):

default: Sets a default value for the field each time a new record is created

null: If True, the field can store NULL values. The default is False.

blank: If True, the field is allowed to be empty. The default is False.

unique: If True, the field must be unique across the database table. (Not applicable for Boolean)

choices: A sequence of 2-tuples to use as choices for this field. (Not applicable for BooleanField, ImageField, DateTimeField)

validators: A list of validators to apply to this field. (Not applicable for Boolean)

help_text: Provides a help text for the field.

verbose_name: A human-readable name for the field.

db_index: If True, a database index is created for this field.

editable: If True, the field is editable in forms.

Lets consider an example where we utilize some of these optional arguments

from django.db import models
from django.core.validators import MinLengthValidator, MaxLengthValidator

class MyModel(models.Model):
CATEGORY_CHOICES = [
('tech', 'Technology'),
('health', 'Health'),
('edu', 'Education'),
]

name = models.CharField(max_length=100, null=True, blank=True, db_index=True, editable=True)
category = models.CharField(choices=CATEGORY_CHOICES, verbose_name='Category Name',
validators=[MinLengthValidator(3), MaxLengthValidator(100)],
help_text='Enter the name of the category. Minimum length is 3 characters.',)
email = models.EmailField(unique=True)

Model Relationships:

Django allows you to define relationships between tables that are many to one(ForeignKey), one to one (OneToOneField), and many to many (ManyToManyField).

ForeignKey:

It establishes a one-to-many relationship, where one record in the source model (the model with the ForeignKey) can be associated with multiple records in the target model (the referenced model).

Example: If you have a Book model and an Author model, a ForeignKey from Book to Author represents that each book has exactly one author (many books can share the same author).

The ForeignKey field is typically used on the “many” side of the relationship (e.g., Book).

from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)

def __str__(self):
return self.name

class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)

def __str__(self):
return self.title
from folder_name/models import Author, Book

author = Author.objects.create(name="Ukeme Wilson")
book = Book.objects.create(title="Introduction to Django Models", author=author)

book = Book.objects.get(id=1)
author = book.author # This gives you the related Author instance
print(author.name)

OneToOneField:

This is used to create a one to one relationship between two models. It is essentially a special case of a ForeignKey with unique=True.

from django.db import models

class Person(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()

class Passport(models.Model):
person = models.OneToOneField(Person, on_delete=models.CASCADE)
passport_number = models.CharField(max_length=20)
issue_date = models.DateField()
expiry_date = models.DateField()
from folder_name/models import Person, Passport

person = Person.objects.get(id=1)
passport = person.passport

passport = Passport.objects.get(id=1)
person = passport.person

The basic difference between the above two relationships can be illustrated with examples. In the case of the book-author relationship (one-to-many/foreign-key), each book will have only one author, but an author can have several books. In contrast, in the case of the person-passport relationship (one-to-one), each person will have only one passport, and each passport will belong to only one person.

ManyToManyField:

This is used to define a many-to-many relationship between two models. This means that each instance of one model can be related to multiple instances of another model, and vice versa. Django handles this relationship using an intermediary join table that maintains the associations between the related models.

class Language(models.Model):

name = models.CharField(max_length=50)

def __str__(self):
return self.name

class Programmer(models.Model):
name = models.CharField(max_length=50)
languages = models.ManyToManyField(Language)

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

This implies that each programmer can know multiple languages. Also each language can be known by multiple programmers.

from folder_name/models import Programmer, Language

programmer = Programmer.objects.get(name='Alice')
languages = programmer.languages.all() # Returns a QuerySet of Language objects
print(languages)

language = Language.objects.get(name='Python')
programmers = language.programmer_set.all() # Returns a QuerySet of Programmer objects
print(programmers)

Metadata:

You can declare model-level metadata for your Model by declaring class Meta, as shown.

class Meta:
ordering = ['-my_field_name'] # Sort the table by 'my_field_name' in descending order. The "-" before the field name signifies descending order.
verbose_name = 'BetterName' # Human-readable name for the model in singular form
abstract = True # To treat the class as an abstract class (No table will be created for it))
db_table = "music_album" # The name of the database table to use for the model

These fields in the Meta class are optional.

Wrapping Up

In this article, we’ve explored the versatility and efficiency of Django models. From defining fields and relationships to leveraging the power of Django’s ORM, models form the backbone of any Django application, making data handling seamless and intuitive.

Combining this knowledge with the other different components of Django will provide a robust framework that simplifies your development process and enhances your application’s functionality.

Happy coding!

Let’s Get in Touch! Follow me on:

>GitHub: @bosukeme

>Linkedin: Ukeme Wilson

You can read other of my Medium Articles here

--

--