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 .venv must 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

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.


Never miss a story on Django.wiki

Subscribe for fresh tutorials, snippets, and updates.

By subscribing you agree to our Privacy Policy.