Filter concepts by levelShowing all levels.

Django · Django Field Types

Django Field Types

Text, numeric, date/time, and specialized/file fields — and each one's real gotcha

  • DecimalField, never FloatFieldfor money — binary float rounding is real
  • auto_now vs auto_now_addevery save() vs once, at creation
  • JSONField default=dict, not {}a callable, not a shared mutable literal
  • ImageField needs Pillowinstalled separately, not a Django dependency

1.Text and numeric field types

CharField requires max_length (a bounded string); TextField has none (unbounded). Integer/BigInteger/PositiveInteger differ only in range. DecimalField (max_digits + decimal_places, fixed precision) is for money; FloatField (native float, imprecise) is not.

Key features

  • CharField(max_length=N) is required — an unbounded VARCHAR is a TextField, not a CharField with no max_length
  • TextField has no enforced length limit at the database or model level
  • IntegerField holds roughly ±2.1 billion; BigIntegerField roughly ±9.2 quintillion; PositiveIntegerField is 0 to ~2.1 billion
  • DecimalField(max_digits=10, decimal_places=2) stores an exact Decimal — always the right choice for money
  • FloatField stores a native Python float — fine for scientific/measurement data, wrong for anything requiring exact arithmetic

Text and numeric fields at a glance

Text and numeric fields at a glance
FieldPython typeNotable requirement/gotcha
CharFieldstrmax_length is required
TextFieldstrno length limit enforced
IntegerFieldint±2.1 billion range, all backends
BigIntegerFieldint±9.2 quintillion range
PositiveIntegerFieldint0 to ~2.1 billion — 0 itself is allowed
DecimalFieldDecimalmax_digits + decimal_places both required
FloatFieldfloatbinary floating point — imprecise, never for money
BooleanFieldbooldefault is None unless Field.default is set
Exact base-10 vs. approximate binary

Decimal("0.1") + Decimal("0.2")

Decimal('0.3') — exact

0.1 + 0.2 (float)

0.30000000000000004 — not exact

  1. Decimal("0.1") + Decimal("0.2") — Decimal('0.3') — exact
  2. 0.1 + 0.2 (float) — 0.30000000000000004 — not exact

Command

python
price = models.DecimalField(max_digits=10, decimal_places=2)
# max_digits=10, decimal_places=2 -> up to 99999999.99

DecimalField (exact, max_digits+decimal_places) for money; FloatField (binary, imprecise) never for money. CharField requires max_length; TextField has none.

2.Date and time field types

DateField/DateTimeField/TimeField hold Python date/datetime/time objects; DurationField holds a timedelta. auto_now_add sets the value ONCE at creation; auto_now updates it on EVERY save() — both make the field non-editable and are only applied by Model.save(), never by QuerySet.update().

Key features

  • auto_now_add=True sets the value only when the object is first created — never changes again
  • auto_now=True sets the value to now on every save() call — a true "last modified" timestamp
  • Both auto_now and auto_now_add force editable=False and blank=True automatically — they cannot be set manually via a form
  • Neither auto_now nor auto_now_add is applied by QuerySet.update() — only by Model.save()
  • DurationField stores a timedelta — arithmetic between two DateTimeFields on the same backend can differ subtly from a plain Python timedelta calculation

Date/time fields at a glance

Date/time fields at a glance
FieldPython typeNotable option
DateFielddatetime.dateauto_now / auto_now_add available
DateTimeFielddatetime.datetimeauto_now / auto_now_add available; respects USE_TZ
TimeFielddatetime.timeauto_now / auto_now_add available
DurationFielddatetime.timedeltastored differently per backend — compare within Django, not raw SQL
auto_now_add vs auto_now

auto_now_add

  • Set ONCE, at creation
  • Never changes again
  • A "birth certificate"

auto_now

  • Re-set on EVERY save()
  • A "last modified" stamp
  • Neither applies during QuerySet.update()
  • auto_now_add
    • Set ONCE, at creation
    • Never changes again
    • A "birth certificate"
  • auto_now
    • Re-set on EVERY save()
    • A "last modified" stamp
    • Neither applies during QuerySet.update()

Command

python
class Task(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    duration = models.DurationField(null=True, blank=True)

auto_now_add sets the value once, at creation; auto_now updates it on every save(). Neither applies during a bulk QuerySet.update() — only Model.save() triggers them.

3.Specialized, validated, and file fields

EmailField/URLField/SlugField are CharField plus a built-in validator (and, for SlugField, an automatic db_index). GenericIPAddressField validates and normalizes IPv4/IPv6. JSONField stores JSON-serializable Python data — its default must be a callable (dict, list), never a literal {} or []. FileField/ImageField store a path under MEDIA_ROOT; ImageField additionally requires the Pillow library.

Key features

  • EmailField (max_length=254 default) and URLField (max_length=200 default) are CharField plus EmailValidator/URLValidator
  • SlugField automatically sets db_index=True — slugs are looked up by value often enough that Django defaults to indexing them
  • GenericIPAddressField validates and normalizes both IPv4 and IPv6 — IPv6 addresses are normalized per RFC 4291
  • JSONField's default must be a callable (default=dict, default=list) — never a literal default={} or default=[]
  • ImageField requires the Pillow library installed — it extends FileField with height_field/width_field validation

Specialized, validated, and file fields

Specialized, validated, and file fields
FieldPython typeNotable behavior
UUIDFielduuid.UUIDsee primary-keys-and-field-options for default=uuid.uuid4
EmailFieldstrCharField + EmailValidator, max_length=254 default
URLFieldstrCharField + URLValidator, max_length=200 default
SlugFieldstrCharField + slug validator, db_index=True automatically, max_length=50 default
GenericIPAddressFieldstrvalidates/normalizes IPv4 and IPv6
JSONFielddict / list / str / int / bool / Nonedefault MUST be a callable, e.g. dict, not {}
FileFieldFieldFilepath relative to MEDIA_ROOT
ImageFieldFieldFilerequires Pillow; adds height_field/width_field
EmailField/URLField/SlugField are CharField plus a validator

CharField

raw string storage

+ a built-in validator

EmailValidator / URLValidator / slug rules

EmailField / URLField / SlugField

rejects malformed input before saving

  1. CharField — raw string storage
  2. + a built-in validator — EmailValidator / URLValidator / slug rules
  3. EmailField / URLField / SlugField — rejects malformed input before saving

Command

python
settings = models.JSONField(default=dict)   # callable, not default={}
tags = models.JSONField(default=list)       # callable, not default=[]

JSONField's default must be a callable (dict, not {}); SlugField auto-indexes; EmailField/URLField are CharField plus a validator; ImageField needs Pillow installed.

Remember

  • DecimalField (exact) for money, never FloatField (binary, imprecise). CharField requires max_length; TextField has none.
  • auto_now_add sets the value once, at creation; auto_now updates on every save() — neither applies during a bulk QuerySet.update().
  • JSONField's default must be a callable (dict, not {}); SlugField auto-indexes; ImageField needs Pillow installed.

Pro tip

  • A bulk-updated row needs its auto_now field set explicitly in the .update() call — save()'s special behavior never runs for a bulk update.
  • EmailField/URLField/SlugField are all CharField plus a built-in validator — same storage, extra validation for free.

Next up

  • null vs blank
  • Choices and Enumerations
  • Relationships

Sources

  • Model field reference — docs.djangoproject.com/en/5.2/ref/models/fields/
  • Every claim checked against Django 5.2 LTS docs · checked 2026-08-21

Spotted a mistake on this page? Tell us.