Model Meta Options
Control database table names, ordering, verbose names, permissions, constraints, and default related names using the Meta class.
1. Introduction
The Meta class sits inside a model and controls how Django treats that model — its database table name, default ordering, human-readable names, permissions, and more. None of these options affect the model's fields directly, but they change how the model behaves across the admin, ORM, and forms.
- You should already be comfortable defining models with fields and relationships.
- Your
.venvmust be active and Django 5.2 installed.
2. Basic structure
The Meta class is defined inside the model class. It has no required options — use only what you need:
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created']
verbose_name = 'Article'
verbose_name_plural = 'Articles'
def __str__(self):
return self.title
3. ordering
Sets the default sort order whenever you query the model without specifying .order_by(). Use a list of field names. Prefix with - to sort descending.
class Meta:
ordering = ['-created'] # newest first
ordering = ['title'] # alphabetical
ordering = ['category', 'title'] # by category, then title within each
ORDER BY clause to every query on that model. On large tables this can slow queries down. If you only need ordering in specific places, use .order_by() on the queryset instead of setting it in Meta.
4. verbose_name and verbose_name_plural
These control the human-readable name shown in the Django admin and in form labels. Django generates them automatically from the class name if you do not set them — Article becomes article and articles.
class Meta:
verbose_name = 'Blog Article'
verbose_name_plural = 'Blog Articles'
Set these when the auto-generated name is wrong — for example Django turns FAQ into f a q which is not what you want.
5. db_table
By default Django names the database table appname_modelname. Use db_table to override this:
class Meta:
db_table = 'blog_articles'
You rarely need this for new projects. It is most useful when connecting Django to an existing database that already has tables with fixed names.
6. unique_together and constraints
unique_together enforces that a combination of fields must be unique across all rows. For example, a user can only review a product once:
class Review(models.Model):
user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
product = models.ForeignKey('Product', on_delete=models.CASCADE)
rating = models.PositiveSmallIntegerField()
class Meta:
unique_together = [('user', 'product')]
unique_together still works but Django now recommends using UniqueConstraint in the constraints list instead — it is more flexible and supports conditions. We cover this in the Model Constraints tutorial.
7. indexes
Add database indexes to speed up queries. Define them in the indexes list inside Meta:
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
status = models.CharField(max_length=20)
created = models.DateTimeField(auto_now_add=True)
class Meta:
indexes = [
models.Index(fields=['status', 'created']),
models.Index(fields=['slug']),
]
We cover indexes in full detail in the Database Indexes tutorial.
8. permissions
Django automatically creates four permissions for each model: add, change, delete, and view. You can add custom permissions in Meta:
class Meta:
permissions = [
('can_publish', 'Can publish articles'),
('can_feature', 'Can feature articles on homepage'),
]
Custom permissions appear in the admin under the model's permission section and can be assigned to users and groups like any built-in permission.
9. get_latest_by
Enables the .latest() and .earliest() queryset methods without passing a field name each time:
class Meta:
get_latest_by = 'created'
# With get_latest_by set
Article.objects.latest() # most recently created article
Article.objects.earliest() # oldest article
10. Putting it together
Here is a model using several Meta options together:
from django.db import models
class Article(models.Model):
class Status(models.TextChoices):
DRAFT = 'draft', 'Draft'
PUBLISHED = 'published', 'Published'
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=220, unique=True)
content = models.TextField()
status = models.CharField(max_length=20, choices=Status, default=Status.DRAFT)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created']
verbose_name = 'Article'
verbose_name_plural = 'Articles'
get_latest_by = 'created'
indexes = [
models.Index(fields=['status', 'created']),
]
permissions = [
('can_publish', 'Can publish articles'),
]
def __str__(self):
return self.title
11. Next steps
You now know the most useful Meta options and when to apply them. The next step covers model methods and properties — how to add behavior and validation directly to your models.