Models are the single source of truth for your data; the ORM, admin, forms and migrations all derive from them.
A model is a class subclassing models.Model; each class attribute that is a field becomes a column:
- text:
CharField(max_length=200),TextField(),SlugField(),EmailField(),URLField() - numbers:
IntegerField,PositiveIntegerField,DecimalField(max_digits=8, decimal_places=2)for money,FloatField - others:
BooleanField,DateField,DateTimeField,UUIDField,JSONField,FileField,ImageField
Every model gets an automatic primary key id, a 64-bit BigAutoField by default in Django 6.0.
Common field options:
null=True: the database column allows NULLblank=True: forms and validation allow an empty valuedefault=...: Python-side default;db_default=...sets it in the databaseunique=True,db_index=True,verbose_name,help_textchoices=: limit values, usually with aTextChoicesorIntegerChoicesenum. Django addsget_<field>_display()for the label.
null and blank are different: one is about the database, the other about validation. For text fields, prefer blank=True with an empty string over null=True, so there is only one "empty" value.
DateTimeField(auto_now_add=True) sets the creation time once; auto_now=True updates on every save.
Always define __str__, since it is used in the admin, the shell and error messages. Model options go in an inner class Meta, such as ordering, verbose_name_plural, indexes and constraints.
Example
# blog/models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
def __str__(self):
return self.name
class Post(models.Model):
class Status(models.TextChoices):
DRAFT = "draft", "Draft"
PUBLISHED = "pub", "Published"
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
body = models.TextField(blank=True)
status = models.CharField(max_length=5, choices=Status, default=Status.DRAFT)
views = models.PositiveIntegerField(default=0)
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-created"]
def __str__(self):
return self.title # post.get_status_display() -> "Published"Remember
- Subclass models.Model; field attributes become columns
- null is about the database, blank about validation
- Use TextChoices/IntegerChoices for fixed sets of values
- Always define __str__
Watch out for
- Using null=True on CharField/TextField, giving two kinds of empty: NULL and "".