Django model support for Litestar, implemented via Litestar DTOs.
from litestar import get, Litestar
from litestar_django import DjangoModelPlugin
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Genre(models.Model):
name = models.CharField(max_length=50)
class Book(models.Model):
name = models.CharField()
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="books")
genres = models.ManyToManyField(Genre, related_name="books")
@get("/{author_id:int}")
async def handler(author_id: int) -> Author:
return await Author.objects.prefetch_related("books").aget(id=author_id)
app = Litestar([handler], plugins=[DjangoModelPlugin()])
This minimal setup will provide serialization of Django objects returned from handlers, complete with OpenAPI schema generation.
pip install litestar-django
from litestar import get
from litestar_django import DjangoModelDTO
from app.models import Author
@get("/{author_id:int}", dto=DjangoModelDTO[Author])
async def handler(author_id: int) -> Author:
return await Author.objects.prefetch_related("books").aget(id=author_id)
from litestar import get
from litestar_django import DjangoModelPlugin
from app.models import Author
@get("/{author_id:int}")
async def handler(author_id: int) -> Author:
return await Author.objects.prefetch_related("books").aget(id=author_id)
app = Litestar([handler], plugins=[DjangoModelPlugin()])
from typing import Annotated
from litestar import post
from litestar.dto import DTOConfig
from litestar_django import DjangoModelDTO
from app.models import Author
@post(
"/",
sync_to_thread=True,
dto=DjangoModelDTO[
Annotated[
Author,
# exclude primary key and relationship fields
DTOConfig(exclude={"id", "books"})
]
],
return_dto=DjangoModelDTO[Author],
)
async def handler(data: Author) -> Author:
await data.asave()
return data
Full OpenAPI schemas are generated from models based on their field types:
Field | OpenAPI type | OpenAPI format |
---|---|---|
models.JSONField |
{} |
|
models.DecimalField |
number |
|
models.DateTimeField |
string |
date-time |
models.DateField |
string |
date |
models.TimeField |
string |
duration |
models.DurationField |
string |
duration |
models.FileField |
string |
|
models.FilePathField |
string |
|
models.UUIDField |
string |
uuid |
models.IntegerField |
integer |
|
models.FloatField |
number |
|
models.BooleanField |
boolean |
|
models.CharField |
string |
|
models.TextField |
string |
|
models.BinaryField |
string |
byte |
The following properties are extracted from fields, in addition to its type:
OpenAPI property | From |
---|---|
title |
Field.verbose_name |
description |
Field.help_text |
enum |
Field.choices |
exclusiveMinimum |
MinValueValidator |
exclusiveMaximum |
MaxValueValidator |
minLength |
MinLengthValidator |
maxLength |
MaxLengthValidator |
Relationships will be represented as individual components, referenced in the schema.
Important
Since lazy-loading is not supported in an async context, you must ensure to always
load everything consumed by the DTO. Not doing so will result in a
SynchronousOnlyOperation
exception being raised by Django
This can be mitigated by:
- Setting
include
orexclude
rules to only include necessary fields (docs) - Configuring nested relationships with an appropriate
max_nexted_depth
(docs) - Using
select_related
andprefetch_related
to ensure relationships are fully loaded
When defining a ForeignKey
field, Django will implicitly generate another field on the
model with an _id
suffix, to store the actual foreign key value. The DTO will include
these implicit fields.
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
name = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="books")
In this example, the DTO for Book
includes the field definitions
id: int
name: str
author_id: int
author: Author
Additionally, the following 3rd party fields / types are supported if the
DjangoModelPlugin
is installed:
django-enumfields
django-enumfields2
All Litestar Organization projects are open for contributions of any size and form.
If you have any questions, reach out to us on Discord or our org-wide GitHub discussions page.
An official Litestar Organization Project