# 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.



<img width="1350" height="600" alt="Screenshot 2025-07-17 at 2 42 18 PM" src="https://github.com/user-attachments/assets/03e109d3-92db-4c9b-8df8-b0c1fedc0b32" />
## 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
```bash
pip install django-admin-query-executor
```
## Quick Start
### Using in Django Admin (QueryExecutorMixin)
1. Add `django_admin_query_executor` to your `INSTALLED_APPS`:
```python
INSTALLED_APPS = [
...
'django_admin_query_executor',
...
]
```
2. Add the `QueryExecutorMixin` to your `ModelAdmin` classes:
```python
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:
```python
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:**
```python
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
```python
# 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
```python
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:
```python
# 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:
```python
@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
```python
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:
```python
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:
```python
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:
```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:**
```python
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
Raw data
{
"_id": null,
"home_page": "https://github.com/j4rf/django-admin-query-executor",
"name": "django-admin-query-executor",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Jeff Turner <jeff@torusoft.com>",
"keywords": "django, admin, query, executor, orm, database, django-admin",
"author": "Jeff Turner",
"author_email": "Jeff Turner <jeff@torusoft.com>",
"download_url": "https://files.pythonhosted.org/packages/33/b0/36d9a76aafb6b177b18cac52284787e6ebe4e6a90aa945be54425aea1183/django_admin_query_executor-1.2.0.tar.gz",
"platform": null,
"description": "# Django Admin Query Executor\n\nA 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.\n\n\n\n\n\n<img width=\"1350\" height=\"600\" alt=\"Screenshot 2025-07-17 at 2 42 18\u202fPM\" src=\"https://github.com/user-attachments/assets/03e109d3-92db-4c9b-8df8-b0c1fedc0b32\" />\n\n## Features\n\n- **Direct Query Execution**: Execute Django ORM queries directly from the admin changelist view\n- **Seamless Integration**: Query results replace the standard admin list view\n- **Full Django ORM Support**: Use `Q()`, `F()`, `Count()`, `Sum()`, `Avg()`, and other Django model functions\n- **Custom Imports**: Add your own modules, functions, and classes to the query execution environment\n- **Query History**: Automatically saves your recent queries for quick re-execution\n- **Favorite Queries**: Save frequently used queries with custom names\n- **Collapsible Interface**: Clean, collapsible UI that doesn't clutter your admin\n- **Comprehensive Dark Mode Support**:\n - Automatically adapts to system preferences\n - Compatible with Django admin's built-in dark mode\n - Works with popular admin themes (Grappelli, Jazzmin, etc.)\n - Smooth transitions between light and dark themes\n - Accessible color contrasts in both modes\n- **Security**: Queries execute in a restricted environment with whitelisted functions\n- **Smart Result Detection**: Automatically handles both queryset and scalar results\n\n## Installation\n\n```bash\npip install django-admin-query-executor\n```\n\n## Quick Start\n\n### Using in Django Admin (QueryExecutorMixin)\n\n1. Add `django_admin_query_executor` to your `INSTALLED_APPS`:\n\n```python\nINSTALLED_APPS = [\n ...\n 'django_admin_query_executor',\n ...\n]\n```\n\n2. Add the `QueryExecutorMixin` to your `ModelAdmin` classes:\n\n```python\nfrom django.contrib import admin\nfrom django_admin_query_executor import QueryExecutorMixin\nfrom .models import MyModel\n\n@admin.register(MyModel)\nclass MyModelAdmin(QueryExecutorMixin, admin.ModelAdmin):\n list_display = ['id', 'name', 'created_at']\n\n # Optional: Define custom example queries for this model\n query_examples = [\n (\"Active items\", \"MyModel.objects.filter(is_active=True)\"),\n (\"Recent items\", \"MyModel.objects.filter(created_at__gte=timezone.now() - timedelta(days=7))\"),\n (\"Count by status\", \"MyModel.objects.values('status').annotate(count=Count('id'))\"),\n ]\n```\n\n### Using as Standalone Function (execute_django_query)\n\nYou can also use the query executor outside the admin interface in your views, management commands, APIs, Celery tasks, or scripts:\n\n```python\nfrom django_admin_query_executor import execute_django_query\nfrom myapp.models import Book\n\n# Execute a query from a string\nresult = execute_django_query(\n \"objects.filter(price__gte=20).count()\",\n Book\n)\nprint(f\"Books priced $20 or more: {result}\")\n\n# With custom imports\ncustom_imports = {\n 'json': 'json',\n 'timedelta': ('datetime', 'timedelta'),\n}\nbooks = execute_django_query(\n \"objects.filter(created_date__gte=now() - timedelta(days=30))\",\n Book,\n custom_imports=custom_imports\n)\n```\n\n**Function Signature:**\n```python\nexecute_django_query(query_string, model, custom_imports=None)\n```\n\n**Parameters:**\n- `query_string` (str): The Django ORM query string to execute\n- `model` (Model): The Django model class to use as the base model\n- `custom_imports` (dict, optional): Additional imports to make available in the query\n\n**Returns:** QuerySet or other result (int, dict, etc.) depending on the query\n\n**Raises:** `ValueError` if there's a syntax error or execution error in the query\n\n**Use Cases:**\n- Django management commands for running scheduled queries\n- API endpoints that accept dynamic query strings\n- Celery tasks for background query execution\n- Admin actions with custom query logic\n- Testing and debugging scripts\n\nSee `example_usage.py` for detailed examples including usage in management commands, views, APIs, and Celery tasks.\n\n## Usage (Admin Interface)\n\n1. Navigate to any model's admin changelist that uses `QueryExecutorMixin`\n2. Click \"Execute Django Query\" to expand the query interface\n3. Enter your Django ORM query (e.g., `MyModel.objects.filter(status='active')`)\n4. Click \"Execute Query\"\n5. The admin list updates to show your query results\n\n### Query Examples\n\n```python\n# Filter queries\nBook.objects.filter(author__name__icontains='Smith')\nBook.objects.filter(Q(title__icontains='Django') | Q(title__icontains='Python'))\n\n# Annotations and aggregations\nBook.objects.annotate(review_count=Count('reviews')).filter(review_count__gt=10)\nBook.objects.aggregate(avg_price=Avg('price'), total_books=Count('id'))\n\n# Complex queries with joins\nAuthor.objects.filter(books__published_date__year=2023).distinct()\nBook.objects.select_related('author', 'publisher').filter(price__lt=50)\n\n# Counting and existence checks\nBook.objects.filter(category='Fiction').count()\nBook.objects.filter(reviews__rating__gte=4).exists()\n\n# Using custom imports (see Custom Imports section)\nBook.objects.filter(title__in=json.loads('[\\\"Book1\\\", \\\"Book2\\\"]'))\nBook.objects.filter(created_date__gte=datetime.now() - timedelta(days=30))\n```\n\n### Standalone Function Examples\n\n```python\nfrom django_admin_query_executor import execute_django_query\nfrom myapp.models import Book, Author\n\n# Basic filtering\nactive_books = execute_django_query(\"objects.filter(is_active=True)\", Book)\n\n# Count query\ncount = execute_django_query(\"objects.filter(price__gte=20).count()\", Book)\n\n# Annotations\nstats = execute_django_query(\n \"objects.aggregate(avg_price=Avg('price'), total=Count('id'))\",\n Book\n)\n\n# Complex queries with Q objects\nbooks = execute_django_query(\n \"objects.filter(Q(category='Fiction') | Q(category='Mystery'))\",\n Book\n)\n\n# With custom imports\nresult = execute_django_query(\n \"objects.filter(published_date__gte=now() - timedelta(days=30))\",\n Book,\n custom_imports={\n 'timedelta': ('datetime', 'timedelta'),\n 'now': ('django.utils.timezone', 'now'),\n }\n)\n```\n\n## Configuration\n\n### Custom Imports\n\nYou can add custom modules, functions, and classes to the query execution environment in two ways:\n\n#### Method 1: Django Settings (Global)\n\nAdd a `QUERY_EXECUTOR_CUSTOM_IMPORTS` setting to your Django settings file:\n\n```python\n# settings.py\nQUERY_EXECUTOR_CUSTOM_IMPORTS = {\n # Import entire modules\n 'json': 'json',\n 'datetime': 'datetime',\n 'timedelta': 'datetime.timedelta',\n 'timezone': 'django.utils.timezone',\n\n # Import specific functions/classes from modules\n 'settings': ('django.conf', 'settings'),\n 'Decimal': ('decimal', 'Decimal'),\n\n # Import your custom models and functions\n 'Listing': 'numi.models.Listing',\n 'Coin': 'numi.models.Coin',\n 'custom_function': 'myapp.utils.custom_function',\n}\n```\n\n#### Method 2: ModelAdmin Class Attribute (Per-Admin)\n\nOverride the `custom_imports` attribute in your ModelAdmin:\n\n```python\n@admin.register(PossibleMatch)\nclass PossibleMatchAdmin(QueryExecutorMixin, admin.ModelAdmin):\n # Custom imports specific to this admin\n custom_imports = {\n 'json': 'json',\n 'settings': ('django.conf', 'settings'),\n 'Listing': 'numi.models.Listing',\n 'Coin': 'numi.models.Coin',\n 'timedelta': ('datetime', 'timedelta'),\n 'now': ('django.utils.timezone', 'now'),\n }\n\n query_examples = [\n (\"High confidence matches\", \"PossibleMatch.objects.filter(textual_score__gt=0.8, image_score__gt=0.8)\"),\n (\"Recent matches\", \"PossibleMatch.objects.filter(textual_match_date__gte=now() - timedelta(days=7))\"),\n (\"Using settings\", \"PossibleMatch.objects.filter(textual_score__gte=settings.TEXTUAL_SCORE_CUTOFF)\"),\n (\"With JSON data\", \"PossibleMatch.objects.filter(id__in=json.loads('[1, 2, 3]'))\"),\n ]\n```\n\n#### Import Format Examples\n\n```python\ncustom_imports = {\n # Simple module imports\n 'json': 'json', # import json\n 'os': 'os', # import os\n\n # Import specific items from modules\n 'settings': ('django.conf', 'settings'), # from django.conf import settings\n 'timezone': ('django.utils', 'timezone'), # from django.utils import timezone\n 'timedelta': ('datetime', 'timedelta'), # from datetime import timedelta\n 'Decimal': ('decimal', 'Decimal'), # from decimal import Decimal\n\n # Import your custom models\n 'User': ('django.contrib.auth.models', 'User'), # from django.contrib.auth.models import User\n 'MyModel': ('myapp.models', 'MyModel'), # from myapp.models import MyModel\n\n # Import custom functions/utilities\n 'my_function': ('myapp.utils', 'my_function'), # from myapp.utils import my_function\n 'calculate_score': ('myapp.scoring', 'calculate_score'),\n}\n```\n\n### Custom Change List Templates\n\nThe 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`:\n\n```\n{% extends \"admin/query_executor_change_list.html\" %}\n```\n\n### Custom Example Queries\n\nDefine model-specific example queries by adding a `query_examples` attribute to your ModelAdmin:\n\n```python\nclass BookAdmin(QueryExecutorMixin, admin.ModelAdmin):\n query_examples = [\n (\"Bestsellers\", \"Book.objects.filter(is_bestseller=True)\"),\n (\"By price range\", \"Book.objects.filter(price__gte=20, price__lte=50)\"),\n (\"Review stats\", \"Book.objects.annotate(avg_rating=Avg('reviews__rating')).filter(avg_rating__gte=4.0)\"),\n (\"Using custom imports\", \"Book.objects.filter(created_date__gte=now() - timedelta(days=30))\"),\n ]\n```\n\n### Customizing Query History\n\nControl the number of queries saved in history:\n\n```python\nclass BookAdmin(QueryExecutorMixin, admin.ModelAdmin):\n query_history_limit = 10 # Default is 5\n```\n\n## Supported Django ORM Features\n\n### Query Methods\n- `filter()`, `exclude()`, `get()`\n- `order_by()`, `reverse()`, `distinct()`\n- `values()`, `values_list()`\n- `select_related()`, `prefetch_related()`\n- `annotate()`, `aggregate()`\n- `first()`, `last()`, `exists()`, `count()`\n\n### Query Expressions\n- `Q()` for complex queries\n- `F()` for field references\n- `Count()`, `Sum()`, `Avg()`, `Max()`, `Min()`\n- `Case()`, `When()` for conditional expressions\n- `Exists()`, `OuterRef()`, `Subquery()`\n\n### Database Functions\n- String functions: `Lower()`, `Upper()`, `Length()`, `Concat()`\n- Date functions: `TruncDate()`, `Extract()`, `Now()`\n- Type casting: `Cast()`, `Coalesce()`\n\n## Dark Mode Support\n\nThe package includes comprehensive dark mode support that:\n\n- **Auto-detects** your system's color scheme preference\n- **Integrates seamlessly** with Django admin's native dark mode\n- **Supports popular admin themes** including:\n - Django's built-in dark mode\n - Grappelli dark theme\n - Django Jazzmin dark mode\n - Django Admin Interface dark themes\n- **Provides smooth transitions** when switching between themes\n- **Ensures accessibility** with proper color contrasts\n- **Includes custom CSS variables** for easy customization\n\n### Customizing Dark Mode Colors\n\nYou can override the default colors by adding CSS variables to your admin CSS:\n\n```css\n.query-executor-container {\n --qe-bg-primary: #1a1a1a;\n --qe-text-primary: #ffffff;\n --qe-button-primary-bg: #007bff;\n /* See query_executor_dark_mode.css for all available variables */\n}\n```\n\n## Security\n\nThe query executor runs in a restricted environment with:\n- Whitelisted functions and classes only\n- No access to private attributes or methods\n- No direct database access beyond Django ORM\n- No file system or network access\n- Custom imports are loaded with error handling\n- Failed imports are logged but don't break functionality\n\n## Requirements\n\n- Django >= 3.2\n- Python >= 3.8\n\n## License\n\nMIT License - see LICENSE file for details\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## API Reference\n\n### `execute_django_query(query_string, model, custom_imports=None)`\n\nStandalone function for executing Django ORM queries from text strings outside the admin interface.\n\n**Parameters:**\n- `query_string` (str): Django ORM query string (e.g., `\"objects.filter(status='active').count()\"`)\n- `model` (django.db.models.Model): The Django model class to query\n- `custom_imports` (dict, optional): Additional modules/functions to make available\n - Format: `{alias: module_path}` or `{alias: (module_path, attribute)}`\n - Example: `{'json': 'json', 'MyModel': ('myapp.models', 'MyModel')}`\n\n**Returns:**\n- QuerySet, int, dict, or other result depending on the query\n\n**Raises:**\n- `ValueError`: If there's a syntax error or execution error in the query\n\n**Security:**\n- Queries execute in a restricted environment with whitelisted functions only\n- No access to private attributes, file system, or network\n- Custom imports are loaded with error handling\n\n**Example:**\n```python\nfrom django_admin_query_executor import execute_django_query\nfrom myapp.models import Book\n\n# Simple usage\nbooks = execute_django_query(\"objects.filter(price__lt=30)\", Book)\n\n# With custom imports\nresult = execute_django_query(\n \"objects.filter(created__gte=now() - timedelta(days=7))\",\n Book,\n custom_imports={\n 'timedelta': ('datetime', 'timedelta'),\n 'now': ('django.utils.timezone', 'now'),\n }\n)\n```\n\n## Changelog\n\n### 1.2.0 (TBD)\n- Added standalone `execute_django_query()` function for use outside admin interface\n- Function can be used in management commands, views, APIs, Celery tasks, and scripts\n- Refactored internal implementation to share code between mixin and standalone function\n\n### 1.1.0 (2025-01-17)\n- Added custom imports support via Django settings and ModelAdmin attribute\n\n### 1.0.0 (2025-07-17)\n- Initial release\n- Full Django ORM query support\n- Query history and favorites\n- Dark mode support\n- Collapsible interface\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Execute Django ORM queries directly from the admin interface",
"version": "1.2.0",
"project_urls": {
"Changelog": "https://github.com/j4rf/django-admin-query-executor/blob/main/CHANGELOG.md",
"Documentation": "https://github.com/j4rf/django-admin-query-executor/blob/main/README.md",
"Homepage": "https://github.com/j4rf/django-admin-query-executor",
"Issues": "https://github.com/j4rf/django-admin-query-executor/issues",
"Repository": "https://github.com/j4rf/django-admin-query-executor"
},
"split_keywords": [
"django",
" admin",
" query",
" executor",
" orm",
" database",
" django-admin"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "d5b8cad021a3f9ba1810d5d33b708cf0af03bc1828a0af3c4f58a1ecfda783b1",
"md5": "ac3ce006a7228b7c2592004bbe985a01",
"sha256": "f6accf89e20b3aaba925481686f69c138bcc6abf8c0207dbbfceff7cde8b4e89"
},
"downloads": -1,
"filename": "django_admin_query_executor-1.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ac3ce006a7228b7c2592004bbe985a01",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 20050,
"upload_time": "2025-10-27T15:09:44",
"upload_time_iso_8601": "2025-10-27T15:09:44.825152Z",
"url": "https://files.pythonhosted.org/packages/d5/b8/cad021a3f9ba1810d5d33b708cf0af03bc1828a0af3c4f58a1ecfda783b1/django_admin_query_executor-1.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "33b036d9a76aafb6b177b18cac52284787e6ebe4e6a90aa945be54425aea1183",
"md5": "36be36f3b5531acd51d8932566c20be8",
"sha256": "c95215b122de0a9ebfec5f2079d2594155c809bd06f2c0461a3a489aa6a31d7f"
},
"downloads": -1,
"filename": "django_admin_query_executor-1.2.0.tar.gz",
"has_sig": false,
"md5_digest": "36be36f3b5531acd51d8932566c20be8",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 25131,
"upload_time": "2025-10-27T15:09:46",
"upload_time_iso_8601": "2025-10-27T15:09:46.079682Z",
"url": "https://files.pythonhosted.org/packages/33/b0/36d9a76aafb6b177b18cac52284787e6ebe4e6a90aa945be54425aea1183/django_admin_query_executor-1.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-27 15:09:46",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "j4rf",
"github_project": "django-admin-query-executor",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "django-admin-query-executor"
}