Skip to main content

django_queryset_annotations

The django_queryset_annotations library provides a way to add annotations to Django querysets. Annotations are additional fields that are calculated on the fly and added to the queryset results. This can be particularly useful when you want to add computed fields to your models without having to modify the underlying database schema.

Installation

You can install django_queryset_annotations via pip:

pip install queryset-annotations

Usage

To use the django_queryset_annotations library, you first need to create an annotation class. An annotation class is a subclass of the BaseAnnotation class. The BaseAnnotation class provides a number of methods that you can use to define the annotation, such as the name, output_field, and get_expression() methods.

Example

Consider the following models:

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey("Author", on_delete=models.CASCADE, related_name="books")


class Author(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()

You can create an annotation class to count the number of books for each author:

from django.db import models
from queryset_annotations.base import BaseAnnotation

class BookCountAnnotation(BaseAnnotation):
    name = "book_count"
    output_field = models.IntegerField()

    def get_expression(self):
        return models.Count("books", distinct=True)

Then, create a proxy model for the Author model:

from queryset_annotations.proxy.model import BaseProxyModel

class AuthorProxyModel(BaseProxyModel):
    book_count = BookCountAnnotation()

    class Meta:
        model = Author

You can now use this proxy model in your serializers and viewsets:

from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = AuthorProxyModel
        fields = "__all__"


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"


class AuthorViewSet(ModelViewSet):
    queryset = AuthorProxyModel.objects.all()
    serializer_class = AuthorSerializer


class BookViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

With this setup, when you retrieve an author from the API, you will also get the count of books they have written.

Advanced Usage

The django_queryset_annotations library also provides a BaseContextManager and an AnnotatedQuerysetMixin for more advanced use cases. The BaseContextManager can be used to manage the context of the annotation, and the AnnotatedQuerysetMixin can be used to automatically annotate the queryset in a viewset.

Here is an example of how to use these features:

from django.db import models
from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet

from annotation.models import Author, Book
from queryset_annotations.base import BaseAnnotation, BaseContextManager
from queryset_annotations.drf.views import AnnotatedQuerysetMixin
from queryset_annotations.proxy.model import BaseProxyModel

class BookCountAnnotation(BaseAnnotation):
    name = "book_count"
    output_field = models.IntegerField()

    def get_expression(self, *, context_manager: BaseContextManager = None):
        return models.Count("books", distinct=True)


class AuthorProxyModel(BaseProxyModel):
    book_count = BookCountAnnotation()

    class Meta:
        model = Author


class AuthorSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = AuthorProxyModel
        fields = "__all__"


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"


class AuthorViewSet(AnnotatedQuerysetMixin, ModelViewSet):
    annotation_context_class = BaseContextManager
    annotated_model = AuthorProxyModel
    serializer_class = AuthorSerializer

    def get_queryset(self):
        context_manager = self.annotation_context_class(self.get_serializer_context())
        return self.queryset.get_annotated_queryset(context_manager=context_manager)


class BookViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

In this example, the AuthorViewSet uses the AnnotatedQuerysetMixin and a BaseContextManager to automatically annotate the queryset with the book count.

Conclusion

The django_queryset_annotations library provides a powerful and flexible way to add computed fields to your Django models. Whether you need to add simple counts or more complex calculations, this library can help you keep your code clean and maintainable.

Metadata

Release files for queryset-annotations 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for queryset-annotations 1.1.0
File Size Uploaded Provenance
queryset_annotations-1.1.0.tar.gz 12.6 kB Without provenance Details

Release files / queryset_annotations-1.1.0.tar.gz

Download URL queryset_annotations-1.1.0.tar.gz
Size 12.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f32ddb80e4926c16344221dcc49ad273a656869e7c6466ef7090979f3063505f
BLAKE2b-256 checksum
How to use checksums
3fceaa306ecf6ce0757dabbb632a7cc3ef5a35202c38f8d68a378086a6b3d1b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.11.4

Security for queryset-annotations 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.1.0 This release

1 release file No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page