Django Models
- A Django model is the built-in feature that Django uses to
create tables, their fields, and various constraints
. - Each model class maps to a single table in the database.
- Django Model is a subclass of
django.db.models.Model
and each field of the model class represents a database field (column).
from django.db import models
class Employee(models.Model):
first_name = models.CharField(max_length=30)
4.1 Field types
- It tells the database what kind of data to store
- Like Integer, Varchar, Boolean etc
# It is an IntegerField that automatically increments.
models.AutoField()
models.BigAutoField()
# A field to store text-based values.
models.CharField(max_length=10)
# A true/false field.
models.BooleanField(default=True)
# Range −2,147,483,648 (−2^31) to 2,147,483,647 (2^31 − 1).
models.IntegerField()
# Range 0 to 2,147,483,647 (2^31 − 1)
models.PositiveIntegerField(null=True)
# IntegerField and PositiveIntegerField can store
# more tha 18-digit in SQLite
# SmallIntegerField, PositiveSmallIntegerField, BigIntegerField
# FloatField
# A large text field.
# The default form widget for this field is a Textarea.
models.TextField(blank=True)
# It is used for date and time,
# represented in Python by a datetime.datetime instance.
models.DateTimeField(default=timezone.now)
models.DateTimeField(default=None, null=True)
# It is a CharField that checks that the value is a valid email address.
models.EmailField(max_length=254)
models.JSONField(default=list)
# A CharField for a URL, validated by URLValidator.
models.URLField(max_length=200, default=None, null=True)
Relationship Fields
# M2O - ForeignKey
models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
# M2M
models.ManyToManyField(Product)
models.ManyToManyField(Product, through='ProductCollection')
# O2O
models.OneToOneField(OrderProduct, on_delete=models.SET_DEFAULT
Django Choices
class Person(models.Model):
SHIRT_SIZES = (
('S', 'Small'),
('M', 'Medium'),
('L', 'Large'),
)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
p = Person.objects.create(name="Fred Flintstone", shirt_size="L")
print(p.shirt_size)
# L
print(p.get_shirt_size_display())
# Large
class Runner(models.Model):
# choices --> GOLD, SILVER, BRONZE
MedalType = models.TextChoices('MedalType', 'GOLD SILVER BRONZE')
name = models.CharField(max_length=60)
medal = models.CharField(
blank=True, choices=MedalType.choices, max_length=10)
MedalType = models.TextChoices('MedalType', 'GOLD SILVER BRONZE')
MedalType.choices
# [('GOLD', 'Gold'), ('SILVER', 'Silver'), ('BRONZE', 'Bronze')]
Place = models.IntegerChoices('Place', 'FIRST SECOND THIRD')
Place.choices
# [(1, 'First'), (2, 'Second'), (3, 'Third')]
class Card(models.Model):
class Suit(models.IntegerChoices):
DIAMOND = 1
SPADE = 2
HEART = 3
CLUB = 4
suit = models.IntegerField(choices=Suit.choices)
# pip install django-choices
from djchoices import ChoiceItem, DjangoChoices
class Book(models.Model):
class BookType(DjangoChoices):
short_story = ChoiceItem('short', 'Short story')
novel = ChoiceItem('novel', 'Novel')
non_fiction = ChoiceItem('non_fiction', 'Non fiction')
author = models.ForeignKey('Author')
book_type = models.CharField(
max_length=20, choices=BookType.choices,
default=BookType.novel
)
# Person.objects.create(author=my_author, type=Book.BookTypes.short_story)
4.2 Field Options
Field options are the arguments given to each field
for applying some constraint or imparting a particular characteristic to a particular Field.
- Null
- If True, Django will store empty values as NULL in the database.
- Default is
False
.
- Blank
- If True, the field is allowed to be blank.
- Default is
False
.
- Default
- The default value for the field.
- This can be a value or a callable object.
- If callable it will be called every time a new object is created.
- help_text
- Extra “help” text to be displayed with the form widget.
- It’s useful for documentation even if your field isn’t used on a form.
- primary_key
- If True, this field is the primary key for the model.
- And
default pk(id)
will be absent
- editable
- If False, the field will not be displayed in the admin or any other ModelForm.
- They are also skipped during model validation.
- Default is True.
- error_messages
- The error_messages argument lets you
override the default messages
that the field will raise. - Pass in a dictionary with keys matching the error messages you want to override.
- The error_messages argument lets you
- verbose_name
- A
human-readable name
for the field. - If the verbose name isn’t given, Django will automatically create it using the field’s attribute name, converting underscores to spaces.
- A
- db_column
- The
name of the database column
to use for this field. - If this isn’t given, Django will use the field’s name
- The
- validators
- A list of
validators to run for this field
. - See the validators documentation for more information.
- A list of
- Unique
- If True, this field must be
unique throughout the table
.
- If True, this field must be
- max_length
- max length of char that can be stored
max_length=10
- at max only 10 char can be stored
Blank vs Null
- By default, both are
set to False
- Null
- null is
database-related
- Defines if a given database column will accept null values or not
- null is
- Blank
- blank is
validation-related
- It will be used during forms validation
- In admin-panel - this field is not mandatory
- blank is
class Person(models.Model):
# Don't put null=True
bio = models.TextField(max_length=500, blank=True)
# May add null=True
birth_date = models.DateField(null=True, blank=True)
NOTE
:Avoid using null on string-based
fields, such as CharField and TextField.- Otherwise, end up having
two possible values
for “no data” i.e.None
and anempty string
verbose_name
verbose_name
is ahuman-readable name
for the field- If the verbose name isn’t given, Django will automatically create it
- Useful in Admin Panel
first_name = models.CharField(max_length=30)
# First Name
field_name = models.Field(verbose_name = "name")
# Name
first_name = models.CharField("person's first name", max_length=30)
# Person's first name:
Primary key
- Django has a default PK,
id
which is automatically created - PK is
like an Index
for the model - If any other field has
primary_key=True
then defaultpk(id) will be absent
# This field will become primary key for the model.
field_name = models.AutoField(primary_key=True)
Unique key
- If True, this field must be unique throughout the table.
- This option is valid on all field types
except ManyToManyField and OneToOneField
# Can't save duplicate values in field_name
field_name = models.Field(unique=True)
PK vs UK
- One model has
- 1 PK fields
- Many UK fields
- Null Value
- PK don’t accept null value
- UK accepts null value
4.3 Model definition
from django.db import models
class Posts(models.Model):
title = models.CharField(max_length=100)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(Person, on_delete=models.CASCADE)
def was_published_recently(self):
diff = timezone.now() - datetime.timedelta(days=1)
return self.date_posted >= diff
def __str__(self):
return self.title
class Meta:
ordering = ['title']
def save(self, *args, **kwargs):
do_something()
# Call the "real" save() method.
super().save(*args, **kwargs)
do_something_else()
- Efficient model import
# Can be anywhere, Order not necessary
ingredients = models.ManyToManyField('Ingredient')
# Also solves Circular import issue
# Ingredient model should be defined before this model
ingredients = models.ManyToManyField(Ingredient)
4.4 ForeignKey.on_delete
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
class Comment(models.Model):
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
- CASCADE
- Whenever the referenced object is deleted, the objects referencing it are deleted as well.
On Post delete, all Comments are also deleted
- SET_NULL
- Set the
ForeignKey null
, this is only possible if null is True.
- Set the
- SET_DEFAULT
- Set the ForeignKey to its
default value
, a default for the ForeignKey must be set.
- Set the ForeignKey to its
- DO_NOTHING
- Do nothing - Consistency must be handled elsewhere
- PROTECT
- Prevent deletion of the referenced object by raising ProtectedError
- RESTRICT
- Prevent deletion of the referenced object by raising RestrictedError
- SET()
- Set the ForeignKey to the value passed to SET()
4.5 Meta Class in Django Models
- It is the
inner class
of your model class. - It is used to
change the behavior
of your model fields
from django.db import models
class Common(models.Model):
name = models.CharField(max_length=100)
class Meta:
abstract = True
class Student(Common):
rollno = models.IntegerField()
class Meta:
verbose_name = "stu"
ordering = [-1]
- Abstract Base Class
- Abstract Base Class are useful when you want to
put some common information
into a number of other models - After set
abstract=True
, now it becomes an abstract class not a model, so now youcan’t generate a database table
- Abstract Base Class are useful when you want to
- verbose_name
- verbose_name is basically a
human-readable name for your model
- verbose_name is basically a
- ordering
- ordering = ['-date_posted'] –> Descending order
- ordering = ['-pub_date', ‘author’]
- Order by pub_date descending, then by author ascending
- app_label
- proxy
- permissions
- …read more
4.6 Model instance methods
__str__()
- Return a nice, human-readable representation of the model from the str() method
save()
- Override save function in MODEL
class Student(common):
rollno = models.IntegerField()
modified_datetime = models.DateTimeField(null=True)
def save(self, *args, **kwargs):
if self.pk: # --> obj is updated
self.modified_datetime = get_curtime()
# self.pk is None --> if obj is created
# super(ProductCollection, self).save(*args, **kwargs)
super().save(*args, **kwargs)
models.py
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
from django.core.exceptions import ValidationError
from django.db.models import Q