Skip to main content

Django Admin Query Executor

A powerful Django admin extension that allows you to execute Django ORM queries directly from the admin interface. It supports complex queries including Q() objects, annotations, aggregations, and all standard Django ORM methods.

Django Admin Query Executor Python Support License

Screenshot 2025-07-17 at 2 42 18 PM

Features

  • Direct Query Execution: Execute Django ORM queries directly from the admin changelist view
  • Seamless Integration: Query results replace the standard admin list view
  • Full Django ORM Support: Use Q(), F(), Count(), Sum(), Avg(), and other Django model functions
  • Custom Imports: Add your own modules, functions, and classes to the query execution environment
  • Query History: Automatically saves your recent queries for quick re-execution
  • Favorite Queries: Save frequently used queries with custom names
  • Collapsible Interface: Clean, collapsible UI that doesn't clutter your admin
  • Comprehensive Dark Mode Support:
    • Automatically adapts to system preferences
    • Compatible with Django admin's built-in dark mode
    • Works with popular admin themes (Grappelli, Jazzmin, etc.)
    • Smooth transitions between light and dark themes
    • Accessible color contrasts in both modes
  • Security: Queries execute in a restricted environment with whitelisted functions
  • Smart Result Detection: Automatically handles both queryset and scalar results

Installation

pip install django-admin-query-executor

Quick Start

Using in Django Admin (QueryExecutorMixin)

  1. Add django_admin_query_executor to your INSTALLED_APPS:
INSTALLED_APPS = [
    ...
    'django_admin_query_executor',
    ...
]
  1. Add the QueryExecutorMixin to your ModelAdmin classes:
from django.contrib import admin
from django_admin_query_executor import QueryExecutorMixin
from .models import MyModel

@admin.register(MyModel)
class MyModelAdmin(QueryExecutorMixin, admin.ModelAdmin):
    list_display = ['id', 'name', 'created_at']

    # Optional: Define custom example queries for this model
    query_examples = [
        ("Active items", "MyModel.objects.filter(is_active=True)"),
        ("Recent items", "MyModel.objects.filter(created_at__gte=timezone.now() - timedelta(days=7))"),
        ("Count by status", "MyModel.objects.values('status').annotate(count=Count('id'))"),
    ]

Using as Standalone Function (execute_django_query)

You can also use the query executor outside the admin interface in your views, management commands, APIs, Celery tasks, or scripts:

from django_admin_query_executor import execute_django_query
from myapp.models import Book

# Execute a query from a string
result = execute_django_query(
    "objects.filter(price__gte=20).count()",
    Book
)
print(f"Books priced $20 or more: {result}")

# With custom imports
custom_imports = {
    'json': 'json',
    'timedelta': ('datetime', 'timedelta'),
}
books = execute_django_query(
    "objects.filter(created_date__gte=now() - timedelta(days=30))",
    Book,
    custom_imports=custom_imports
)

Function Signature:

execute_django_query(query_string, model, custom_imports=None)

Parameters:

  • query_string (str): The Django ORM query string to execute
  • model (Model): The Django model class to use as the base model
  • custom_imports (dict, optional): Additional imports to make available in the query

Returns: QuerySet or other result (int, dict, etc.) depending on the query

Raises: ValueError if there's a syntax error or execution error in the query

Use Cases:

  • Django management commands for running scheduled queries
  • API endpoints that accept dynamic query strings
  • Celery tasks for background query execution
  • Admin actions with custom query logic
  • Testing and debugging scripts

See example_usage.py for detailed examples including usage in management commands, views, APIs, and Celery tasks.

Usage (Admin Interface)

  1. Navigate to any model's admin changelist that uses QueryExecutorMixin
  2. Click "Execute Django Query" to expand the query interface
  3. Enter your Django ORM query (e.g., MyModel.objects.filter(status='active'))
  4. Click "Execute Query"
  5. The admin list updates to show your query results

Query Examples

# Filter queries
Book.objects.filter(author__name__icontains='Smith')
Book.objects.filter(Q(title__icontains='Django') | Q(title__icontains='Python'))

# Annotations and aggregations
Book.objects.annotate(review_count=Count('reviews')).filter(review_count__gt=10)
Book.objects.aggregate(avg_price=Avg('price'), total_books=Count('id'))

# Complex queries with joins
Author.objects.filter(books__published_date__year=2023).distinct()
Book.objects.select_related('author', 'publisher').filter(price__lt=50)

# Counting and existence checks
Book.objects.filter(category='Fiction').count()
Book.objects.filter(reviews__rating__gte=4).exists()

# Using custom imports (see Custom Imports section)
Book.objects.filter(title__in=json.loads('[\"Book1\", \"Book2\"]'))
Book.objects.filter(created_date__gte=datetime.now() - timedelta(days=30))

Standalone Function Examples

from django_admin_query_executor import execute_django_query
from myapp.models import Book, Author

# Basic filtering
active_books = execute_django_query("objects.filter(is_active=True)", Book)

# Count query
count = execute_django_query("objects.filter(price__gte=20).count()", Book)

# Annotations
stats = execute_django_query(
    "objects.aggregate(avg_price=Avg('price'), total=Count('id'))",
    Book
)

# Complex queries with Q objects
books = execute_django_query(
    "objects.filter(Q(category='Fiction') | Q(category='Mystery'))",
    Book
)

# With custom imports
result = execute_django_query(
    "objects.filter(published_date__gte=now() - timedelta(days=30))",
    Book,
    custom_imports={
        'timedelta': ('datetime', 'timedelta'),
        'now': ('django.utils.timezone', 'now'),
    }
)

Configuration

Custom Imports

You can add custom modules, functions, and classes to the query execution environment in two ways:

Method 1: Django Settings (Global)

Add a QUERY_EXECUTOR_CUSTOM_IMPORTS setting to your Django settings file:

# settings.py
QUERY_EXECUTOR_CUSTOM_IMPORTS = {
    # Import entire modules
    'json': 'json',
    'datetime': 'datetime',
    'timedelta': 'datetime.timedelta',
    'timezone': 'django.utils.timezone',

    # Import specific functions/classes from modules
    'settings': ('django.conf', 'settings'),
    'Decimal': ('decimal', 'Decimal'),

    # Import your custom models and functions
    'Listing': 'numi.models.Listing',
    'Coin': 'numi.models.Coin',
    'custom_function': 'myapp.utils.custom_function',
}

Method 2: ModelAdmin Class Attribute (Per-Admin)

Override the custom_imports attribute in your ModelAdmin:

@admin.register(PossibleMatch)
class PossibleMatchAdmin(QueryExecutorMixin, admin.ModelAdmin):
    # Custom imports specific to this admin
    custom_imports = {
        'json': 'json',
        'settings': ('django.conf', 'settings'),
        'Listing': 'numi.models.Listing',
        'Coin': 'numi.models.Coin',
        'timedelta': ('datetime', 'timedelta'),
        'now': ('django.utils.timezone', 'now'),
    }

    query_examples = [
        ("High confidence matches", "PossibleMatch.objects.filter(textual_score__gt=0.8, image_score__gt=0.8)"),
        ("Recent matches", "PossibleMatch.objects.filter(textual_match_date__gte=now() - timedelta(days=7))"),
        ("Using settings", "PossibleMatch.objects.filter(textual_score__gte=settings.TEXTUAL_SCORE_CUTOFF)"),
        ("With JSON data", "PossibleMatch.objects.filter(id__in=json.loads('[1, 2, 3]'))"),
    ]

Import Format Examples

custom_imports = {
    # Simple module imports
    'json': 'json',                    # import json
    'os': 'os',                        # import os

    # Import specific items from modules
    'settings': ('django.conf', 'settings'),              # from django.conf import settings
    'timezone': ('django.utils', 'timezone'),             # from django.utils import timezone
    'timedelta': ('datetime', 'timedelta'),               # from datetime import timedelta
    'Decimal': ('decimal', 'Decimal'),                    # from decimal import Decimal

    # Import your custom models
    'User': ('django.contrib.auth.models', 'User'),      # from django.contrib.auth.models import User
    'MyModel': ('myapp.models', 'MyModel'),               # from myapp.models import MyModel

    # Import custom functions/utilities
    'my_function': ('myapp.utils', 'my_function'),        # from myapp.utils import my_function
    'calculate_score': ('myapp.scoring', 'calculate_score'),
}

Custom Change List Templates

The mixin automatically overrides the ModelAdmin's change_list_template if the default template is in use. If your ModelAdmin uses a custom template, the template will need to extend admin/query_executor_change_list.html:

{% extends "admin/query_executor_change_list.html" %}

Custom Example Queries

Define model-specific example queries by adding a query_examples attribute to your ModelAdmin:

class BookAdmin(QueryExecutorMixin, admin.ModelAdmin):
    query_examples = [
        ("Bestsellers", "Book.objects.filter(is_bestseller=True)"),
        ("By price range", "Book.objects.filter(price__gte=20, price__lte=50)"),
        ("Review stats", "Book.objects.annotate(avg_rating=Avg('reviews__rating')).filter(avg_rating__gte=4.0)"),
        ("Using custom imports", "Book.objects.filter(created_date__gte=now() - timedelta(days=30))"),
    ]

Customizing Query History

Control the number of queries saved in history:

class BookAdmin(QueryExecutorMixin, admin.ModelAdmin):
    query_history_limit = 10  # Default is 5

Supported Django ORM Features

Query Methods

  • filter(), exclude(), get()
  • order_by(), reverse(), distinct()
  • values(), values_list()
  • select_related(), prefetch_related()
  • annotate(), aggregate()
  • first(), last(), exists(), count()

Query Expressions

  • Q() for complex queries
  • F() for field references
  • Count(), Sum(), Avg(), Max(), Min()
  • Case(), When() for conditional expressions
  • Exists(), OuterRef(), Subquery()

Database Functions

  • String functions: Lower(), Upper(), Length(), Concat()
  • Date functions: TruncDate(), Extract(), Now()
  • Type casting: Cast(), Coalesce()

Dark Mode Support

The package includes comprehensive dark mode support that:

  • Auto-detects your system's color scheme preference
  • Integrates seamlessly with Django admin's native dark mode
  • Supports popular admin themes including:
    • Django's built-in dark mode
    • Grappelli dark theme
    • Django Jazzmin dark mode
    • Django Admin Interface dark themes
  • Provides smooth transitions when switching between themes
  • Ensures accessibility with proper color contrasts
  • Includes custom CSS variables for easy customization

Customizing Dark Mode Colors

You can override the default colors by adding CSS variables to your admin CSS:

.query-executor-container {
    --qe-bg-primary: #1a1a1a;
    --qe-text-primary: #ffffff;
    --qe-button-primary-bg: #007bff;
    /* See query_executor_dark_mode.css for all available variables */
}

Security

The query executor runs in a restricted environment with:

  • Whitelisted functions and classes only
  • No access to private attributes or methods
  • No direct database access beyond Django ORM
  • No file system or network access
  • Custom imports are loaded with error handling
  • Failed imports are logged but don't break functionality

Requirements

  • Django >= 3.2
  • Python >= 3.8

License

MIT License - see LICENSE file for details

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

API Reference

execute_django_query(query_string, model, custom_imports=None)

Standalone function for executing Django ORM queries from text strings outside the admin interface.

Parameters:

  • query_string (str): Django ORM query string (e.g., "objects.filter(status='active').count()")
  • model (django.db.models.Model): The Django model class to query
  • custom_imports (dict, optional): Additional modules/functions to make available
    • Format: {alias: module_path} or {alias: (module_path, attribute)}
    • Example: {'json': 'json', 'MyModel': ('myapp.models', 'MyModel')}

Returns:

  • QuerySet, int, dict, or other result depending on the query

Raises:

  • ValueError: If there's a syntax error or execution error in the query

Security:

  • Queries execute in a restricted environment with whitelisted functions only
  • No access to private attributes, file system, or network
  • Custom imports are loaded with error handling

Example:

from django_admin_query_executor import execute_django_query
from myapp.models import Book

# Simple usage
books = execute_django_query("objects.filter(price__lt=30)", Book)

# With custom imports
result = execute_django_query(
    "objects.filter(created__gte=now() - timedelta(days=7))",
    Book,
    custom_imports={
        'timedelta': ('datetime', 'timedelta'),
        'now': ('django.utils.timezone', 'now'),
    }
)

Changelog

1.2.0 (TBD)

  • Added standalone execute_django_query() function for use outside admin interface
  • Function can be used in management commands, views, APIs, Celery tasks, and scripts
  • Refactored internal implementation to share code between mixin and standalone function

1.1.0 (2025-01-17)

  • Added custom imports support via Django settings and ModelAdmin attribute

1.0.0 (2025-07-17)

  • Initial release
  • Full Django ORM query support
  • Query history and favorites
  • Dark mode support
  • Collapsible interface

Metadata

Release files for django-admin-query-executor 1.2.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 django-admin-query-executor 1.2.0
File Size Uploaded Provenance Actions
django_admin_query_executor-1.2.0.tar.gz 25.1 kB Without provenance Details for django_admin_query_executor-1.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for django-admin-query-executor 1.2.0
File Interpreter ABI Platform Actions
django_admin_query_executor-1.2.0-py3-none-any.whl Python 3 none any Details for django_admin_query_executor-1.2.0-py3-none-any.whl

Total release size: 45.2 kB

Release files / django_admin_query_executor-1.2.0.tar.gz

Download URL django_admin_query_executor-1.2.0.tar.gz
Size 25.1 kB
Tags Source
SHA-256 checksum
How to use checksums
c95215b122de0a9ebfec5f2079d2594155c809bd06f2c0461a3a489aa6a31d7f
BLAKE2b-256 checksum
How to use checksums
33b036d9a76aafb6b177b18cac52284787e6ebe4e6a90aa945be54425aea1183
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.2

Release files / django_admin_query_executor-1.2.0-py3-none-any.whl

Download URL django_admin_query_executor-1.2.0-py3-none-any.whl
Size 20.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f6accf89e20b3aaba925481686f69c138bcc6abf8c0207dbbfceff7cde8b4e89
BLAKE2b-256 checksum
How to use checksums
d5b8cad021a3f9ba1810d5d33b708cf0af03bc1828a0af3c4f58a1ecfda783b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.2

Security for django-admin-query-executor 1.2.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.

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