# Django jqGrid Package
A comprehensive Django package that provides seamless integration of jqGrid with Django REST Framework, offering powerful data grid functionality with minimal configuration.
## Features
- **Automatic Configuration**: Generates jqGrid configuration from Django model metadata and DRF serializers
- **Full CRUD Support**: Built-in Create, Read, Update, Delete operations via REST API
- **Advanced Features**:
- Multi-column sorting
- Advanced filtering with multiple operators
- Bulk operations (update/delete)
- Row grouping and aggregation
- Frozen columns
- Conditional formatting
- Import/Export functionality
- Custom grid filters per user
- **Responsive Design**: Bootstrap 4/5 compatible with mobile support
- **Security**: Permission-based access control
- **Extensible**: Easy to customize and extend
## Installation
```bash
pip install django-jqgrid
```
## Quick Start
### 1. Add to Installed Apps
```python
INSTALLED_APPS = [
# ...
'rest_framework',
'django_jqgrid',
# ...
]
```
### 2. Include URLs
```python
# urls.py
from django.urls import path, include
urlpatterns = [
# ...
path('api/grid/', include('django_jqgrid.urls')),
# ...
]
```
### 3. Create a ViewSet with JqGrid Mixin
```python
# views.py
from rest_framework import viewsets
from django_jqgrid.mixins import JqGridConfigMixin, JqGridBulkActionMixin
from .models import YourModel
from .serializers import YourModelSerializer
class YourModelViewSet(JqGridConfigMixin, JqGridBulkActionMixin, viewsets.ModelViewSet):
queryset = YourModel.objects.all()
serializer_class = YourModelSerializer
# Optional: Customize visible columns
visible_columns = ['id', 'name', 'email', 'created_at']
# Optional: Define searchable fields
search_fields = ['name', 'email']
# Optional: Define sortable fields
ordering_fields = ['name', 'created_at']
# Optional: Default ordering
ordering = ['-created_at']
```
### 4. Add jqGrid to Your Template
```html
<!-- Include jQuery and jqGrid files -->
<link rel="stylesheet" href="{% static 'django_jqgrid/plugins/jqGrid/css/ui.jqgrid-bootstrap4.css' %}">
<script src="{% static 'django_jqgrid/plugins/jqGrid/js/jquery.jqGrid.min.js' %}"></script>
<script src="{% static 'django_jqgrid/js/jqgrid-integration.js' %}"></script>
<!-- Grid Container -->
<table id="jqGrid"></table>
<div id="jqGridPager"></div>
<script>
$(document).ready(function() {
// Initialize jqGrid with configuration from API
$.getJSON('/api/yourapp/yourmodel/jqgrid_config/', function(config) {
$("#jqGrid").jqGrid(config.jqgrid_options);
// Apply method options
$("#jqGrid").jqGrid('navGrid', '#jqGridPager',
config.method_options.navGrid.options,
config.method_options.navGrid.editOptions,
config.method_options.navGrid.addOptions,
config.method_options.navGrid.delOptions,
config.method_options.navGrid.searchOptions,
config.method_options.navGrid.viewOptions
);
// Apply filter toolbar
$("#jqGrid").jqGrid('filterToolbar', config.method_options.filterToolbar.options);
});
});
</script>
```
## Configuration
### Serializer-Based Configuration
The package automatically configures jqGrid based on your DRF serializer fields:
```python
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
# Read-only fields become non-editable in grid
total_sales = serializers.ReadOnlyField()
# Custom labels are used in grid headers
name = serializers.CharField(label="Product Name")
# Field types determine grid column types
price = serializers.DecimalField(max_digits=10, decimal_places=2)
in_stock = serializers.BooleanField()
created_at = serializers.DateTimeField(read_only=True)
class Meta:
model = Product
fields = ['id', 'name', 'price', 'in_stock', 'total_sales', 'created_at']
```
### Field Type Mappings
The package automatically maps Django field types to jqGrid column configurations:
| Django Field Type | jqGrid Configuration |
|------------------|---------------------|
| CharField | `stype: 'text'`, search operators: eq, ne, cn, nc, bw, bn, ew, en |
| IntegerField | `stype: 'integer'`, `align: 'right'`, search operators: eq, ne, lt, le, gt, ge |
| DecimalField | `stype: 'number'`, `align: 'right'`, with decimal places |
| BooleanField | `stype: 'checkbox'`, `align: 'center'` |
| DateField | `stype: 'date'`, with datepicker |
| DateTimeField | `stype: 'datetime-local'`, with datetimepicker |
| ForeignKey | `stype: 'select'`, with dropdown data URL |
| EmailField | `stype: 'email'`, `formatter: 'email'` |
| URLField | `stype: 'text'`, `formatter: 'link'` |
### ViewSet Configuration Options
```python
class ProductViewSet(JqGridConfigMixin, JqGridBulkActionMixin, viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
# Column visibility
visible_columns = ['id', 'name', 'price', 'in_stock', 'created_at']
# Search configuration
search_fields = ['name', 'description', 'sku']
# Sorting configuration
ordering_fields = ['name', 'price', 'created_at']
ordering = ['-created_at', 'name'] # Default sort
# Grouping configuration
groupable_fields = ['category', 'brand']
# Frozen columns (stay visible when scrolling)
frozen_columns = ['id', 'name']
# Bulk operations
bulk_updateable_fields = ['price', 'in_stock', 'category']
bulk_actions = [
{
'id': 'bulk-update-price',
'label': 'Update Price',
'icon': 'fa-dollar',
'class': 'btn-warning'
},
{
'id': 'bulk-delete',
'label': 'Delete Selected',
'icon': 'fa-trash',
'class': 'btn-danger'
}
]
# Field overrides
jqgrid_field_overrides = {
'price': {
'formatter': 'currency',
'formatoptions': {'prefix': '$', 'decimalPlaces': 2}
}
}
# Grid options override
jqgrid_options_override = {
'rowNum': 50,
'height': 600,
'caption': 'Product Inventory'
}
# Conditional formatting
conditional_formatting = {
'in_stock': {
'false': {'color': 'red', 'background': '#ffeeee'},
'true': {'color': 'green', 'background': '#eeffee'}
},
'price': {
'condition': 'value > 1000',
'style': {'fontWeight': 'bold', 'color': 'blue'}
}
}
```
## Advanced Features
### 1. Bulk Operations
The `JqGridBulkActionMixin` provides bulk update and delete functionality:
```javascript
// Bulk update example
$.ajax({
url: '/api/products/bulk_action/',
method: 'POST',
data: JSON.stringify({
ids: [1, 2, 3],
action: {
price: 29.99,
in_stock: true
}
}),
contentType: 'application/json'
});
// Bulk delete example
$.ajax({
url: '/api/products/bulk_action/',
method: 'POST',
data: JSON.stringify({
ids: [1, 2, 3],
action: {
_delete: true
}
}),
contentType: 'application/json'
});
```
### 2. Custom Grid Filters
Users can save and manage custom grid filters:
```python
# The package includes GridFilter model for storing user filters
from django_jqgrid.models import GridFilter
# Filters are automatically available in the grid search dialog
# Users can save search criteria as named filters
```
### 3. Import/Export Configuration
```python
class ProductViewSet(JqGridConfigMixin, viewsets.ModelViewSet):
# ... other configuration ...
import_config = {
'supported_formats': ['csv', 'xlsx', 'json'],
'field_mapping': {
'Product Name': 'name',
'Price': 'price',
'Stock': 'in_stock'
}
}
export_config = {
'formats': ['csv', 'xlsx', 'pdf'],
'include_headers': True,
'max_rows': 10000
}
```
### 4. Row Grouping
```python
class OrderViewSet(JqGridConfigMixin, viewsets.ModelViewSet):
# ... other configuration ...
groupable_fields = ['status', 'customer', 'date']
aggregation_fields = {
'total': 'sum',
'items_count': 'count'
}
```
## API Endpoints
The package automatically creates these endpoints for each model:
- `GET /api/<app>/<model>/` - List/search records with jqGrid parameters
- `GET /api/<app>/<model>/jqgrid_config/` - Get grid configuration
- `POST /api/<app>/<model>/crud/` - Handle jqGrid CRUD operations
- `POST /api/<app>/<model>/bulk_action/` - Bulk update/delete
- `GET /api/<app>/<model>/dropdown/` - Get dropdown data for foreign keys
## Settings
```python
# settings.py
# Default grid options (optional)
JQGRID_DEFAULT_GRID_OPTIONS = {
'rowNum': 25,
'rowList': [25, 50, 100, 500, 1000],
'height': 400,
'styleUI': 'Bootstrap4',
'iconSet': 'fontAwesome'
}
# Default field type configurations (optional)
JQGRID_DEFAULT_FIELD_CONFIG = {
'DateField': {
'formatoptions': {"srcformat": "ISO8601Short", "newformat": "d/m/Y"}
}
}
```
## JavaScript Integration
The package includes JavaScript utilities for enhanced functionality:
```javascript
// jqgrid-integration.js provides helper functions
// Handle form responses
window.handleFormResponse = function(response, postdata) {
// Custom response handling
};
// Handle export
window.handleExport = function() {
// Export grid data
};
// Handle import
window.handleImport = function() {
// Import data dialog
};
```
## Theme Configuration
Django jqGrid supports multiple themes and can be easily customized to match your application's design.
### Using the Theme Template Tag
```django
{% load jqgrid_tags %}
<!-- Use default theme (Bootstrap 4) -->
{% jqgrid_theme %}
<!-- Specify theme and icon set -->
{% jqgrid_theme 'bootstrap5' 'fontAwesome' %}
<!-- Use custom CSS -->
{% jqgrid_theme theme='bootstrap4' custom_css='/static/css/my-grid-theme.css' %}
```
### Available Themes
- **bootstrap** - Bootstrap 3 theme
- **bootstrap4** - Bootstrap 4 theme (default)
- **bootstrap5** - Bootstrap 5 theme
- **jqueryui** - jQuery UI theme
### Available Icon Sets
- **fontAwesome** - Font Awesome icons (default)
- **bootstrap** - Bootstrap Icons
- **jQueryUI** - jQuery UI icons
- **glyph** - Glyphicons (Bootstrap 3)
### Settings-Based Configuration
Configure theme globally in your Django settings:
```python
# settings.py
JQGRID_THEME = 'bootstrap5'
JQGRID_ICON_SET = 'fontAwesome'
JQGRID_CUSTOM_CSS = '/static/css/custom-grid.css'
```
### Dynamic Theme Switching
Include the theme switcher component:
```html
<!-- Theme switcher container -->
<div id="theme-switcher"></div>
<!-- Include theme switcher JS -->
<script src="{% static 'django_jqgrid/js/jqgrid-theme-switcher.js' %}"></script>
<script>
// Initialize theme switcher
jqGridThemeSwitcher.init({
container: '#theme-switcher',
showPreview: true,
onChange: function(theme, iconSet) {
console.log('Theme changed to:', theme, iconSet);
}
});
</script>
```
### Custom Theme CSS
Create your own theme by overriding CSS variables:
```css
/* custom-grid-theme.css */
:root {
/* Grid colors */
--jqgrid-header-bg: #2c3e50;
--jqgrid-header-text: #ffffff;
--jqgrid-row-hover: #ecf0f1;
--jqgrid-row-selected: #3498db;
/* Borders */
--jqgrid-border-color: #bdc3c7;
/* Fonts */
--jqgrid-font-size: 14px;
--jqgrid-header-font-weight: 600;
}
/* Dark mode support */
@media (prefers-color-scheme: dark) {
:root {
--jqgrid-header-bg: #1a1a1a;
--jqgrid-row-bg: #2a2a2a;
--jqgrid-row-alt-bg: #333333;
}
}
```
## Customization and Extension
Django jqGrid is designed to be highly customizable. Here are some common customization examples:
### Quick Customization Examples
#### 1. Custom Formatters
```javascript
// Register a custom status badge formatter
window.jqGridConfig.formatters.statusBadge = function(cellval, opts) {
const statusClasses = {
'active': 'badge-success',
'pending': 'badge-warning',
'inactive': 'badge-danger'
};
const badgeClass = statusClasses[cellval] || 'badge-info';
return `<span class="badge ${badgeClass}">${cellval}</span>`;
};
// Use in ViewSet
jqgrid_field_overrides = {
'status': {
'formatter': 'statusBadge',
'align': 'center'
}
}
```
#### 2. Custom Bulk Actions
```python
class ProductViewSet(JqGridConfigMixin, JqGridBulkActionMixin, viewsets.ModelViewSet):
# Define custom bulk actions
bulk_actions = [
{
'id': 'apply-discount',
'label': 'Apply Discount',
'icon': 'fa-percent',
'class': 'btn-warning'
}
]
@action(methods=['post'], detail=False)
def bulk_action(self, request):
action_id = request.data.get('action_id')
if action_id == 'apply-discount':
# Custom logic here
return Response({'status': 'success'})
return super().bulk_action(request)
```
#### 3. JavaScript Hooks
```javascript
// Customize grid behavior using hooks
window.jqGridConfig.hooks.beforeInitGrid = function(tableInstance) {
// Add custom configuration before grid initializes
tableInstance.options.customData = { department: 'sales' };
};
window.jqGridConfig.hooks.afterSubmitBulkUpdate = function(tableInstance, ids, action, scope, response) {
// Custom notification after bulk update
showCustomNotification('Updated ' + ids.length + ' records');
};
```
#### 4. Dynamic Column Configuration
```python
class UserAwareProductViewSet(JqGridConfigMixin, viewsets.ModelViewSet):
def get_visible_columns(self):
"""Show different columns based on user permissions"""
base_columns = ['id', 'name', 'price']
if self.request.user.has_perm('products.view_cost'):
base_columns.extend(['cost', 'profit_margin'])
if self.request.user.is_staff:
base_columns.extend(['supplier', 'internal_notes'])
return base_columns
def get_jqgrid_config(self, request):
self.visible_columns = self.get_visible_columns()
return super().get_jqgrid_config(request)
```
#### 5. Custom Toolbar Buttons
```javascript
// Add custom buttons to specific tables
window.jqGridConfig.customButtons.product = [
{
id: 'import-csv',
label: 'Import CSV',
icon: 'fa-file-csv',
class: 'btn-success',
action: function(tableInstance) {
showImportModal(tableInstance);
}
}
];
```
### Complete Customization Guide
For comprehensive customization examples including:
- Advanced ViewSet customization
- Custom field types
- Theme customization
- Real-time updates
- Performance optimization
- Complex real-world examples
See the [**Customization Guide**](CUSTOMIZATION_GUIDE.md).
## Example Project
The package includes a complete example project demonstrating all features:
### Running the Example Project
```bash
# Navigate to example project
cd example_project
# Install dependencies
pip install -r requirements.txt
# Setup the project
python setup_example.py
# Run the server
python manage.py runserver
```
Visit: `http://localhost:8000/`
## Security
- All operations respect Django's permission system
- CSRF protection for all POST requests
- User-specific filters are isolated
- Bulk operations validate field permissions
## Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Mobile browsers (responsive mode)
## Troubleshooting
### Common Issues
#### 1. "jqgrid_tags is not a registered tag library"
**Solution:**
- Ensure `django_jqgrid` is in your `INSTALLED_APPS`
- Restart the Django development server
- If developing locally, install the package in editable mode: `pip install -e .`
#### 2. Grid not loading data
**Solution:**
- Check browser console for JavaScript errors
- Verify the API endpoint is accessible
- Ensure DRF permissions allow access
- Check that the ViewSet URL pattern is correct
#### 3. Bulk operations not working
**Solution:**
- Verify `JqGridBulkActionMixin` is included in your ViewSet
- Check CSRF token is being sent with requests
- Ensure user has appropriate permissions
#### 4. Custom formatters not displaying
**Solution:**
- Register formatters before grid initialization
- Check formatter function name matches configuration
- Verify no JavaScript errors in formatter function
#### 5. Performance issues with large datasets
**Solution:**
- Use server-side pagination (enabled by default)
- Add database indexes on frequently sorted/filtered columns
- Use `select_related()` and `prefetch_related()` in querysets
- Consider implementing caching for frequently accessed data
For more detailed troubleshooting, see the [Customization Guide](CUSTOMIZATION_GUIDE.md#troubleshooting).
## Requirements
- Python 3.8+
- Django 3.2+
- Django REST Framework 3.12+
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## Support
For issues and feature requests, please use the [GitHub issue tracker](https://github.com/coder-aniket/django-jqgrid/issues).
Raw data
{
"_id": null,
"home_page": "https://github.com/coder-aniket/django-jqgrid",
"name": "django-jqgrid",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "django, jqgrid, rest, framework, grid, datatable",
"author": "Your Name",
"author_email": "Django jqGrid Team <support@django-jqgrid.org>",
"download_url": "https://files.pythonhosted.org/packages/c4/62/c5d408e16d4d70e92795c08f8196bbf891b520bc7aeef1d8b58a3ac5ee8d/django_jqgrid-1.2.7.tar.gz",
"platform": null,
"description": "# Django jqGrid Package\r\n\r\nA comprehensive Django package that provides seamless integration of jqGrid with Django REST Framework, offering powerful data grid functionality with minimal configuration.\r\n\r\n## Features\r\n\r\n- **Automatic Configuration**: Generates jqGrid configuration from Django model metadata and DRF serializers\r\n- **Full CRUD Support**: Built-in Create, Read, Update, Delete operations via REST API\r\n- **Advanced Features**:\r\n - Multi-column sorting\r\n - Advanced filtering with multiple operators\r\n - Bulk operations (update/delete)\r\n - Row grouping and aggregation\r\n - Frozen columns\r\n - Conditional formatting\r\n - Import/Export functionality\r\n - Custom grid filters per user\r\n- **Responsive Design**: Bootstrap 4/5 compatible with mobile support\r\n- **Security**: Permission-based access control\r\n- **Extensible**: Easy to customize and extend\r\n\r\n## Installation\r\n\r\n```bash\r\npip install django-jqgrid\r\n```\r\n\r\n## Quick Start\r\n\r\n### 1. Add to Installed Apps\r\n\r\n```python\r\nINSTALLED_APPS = [\r\n # ...\r\n 'rest_framework',\r\n 'django_jqgrid',\r\n # ...\r\n]\r\n```\r\n\r\n### 2. Include URLs\r\n\r\n```python\r\n# urls.py\r\nfrom django.urls import path, include\r\n\r\nurlpatterns = [\r\n # ...\r\n path('api/grid/', include('django_jqgrid.urls')),\r\n # ...\r\n]\r\n```\r\n\r\n### 3. Create a ViewSet with JqGrid Mixin\r\n\r\n```python\r\n# views.py\r\nfrom rest_framework import viewsets\r\nfrom django_jqgrid.mixins import JqGridConfigMixin, JqGridBulkActionMixin\r\nfrom .models import YourModel\r\nfrom .serializers import YourModelSerializer\r\n\r\nclass YourModelViewSet(JqGridConfigMixin, JqGridBulkActionMixin, viewsets.ModelViewSet):\r\n queryset = YourModel.objects.all()\r\n serializer_class = YourModelSerializer\r\n \r\n # Optional: Customize visible columns\r\n visible_columns = ['id', 'name', 'email', 'created_at']\r\n \r\n # Optional: Define searchable fields\r\n search_fields = ['name', 'email']\r\n \r\n # Optional: Define sortable fields\r\n ordering_fields = ['name', 'created_at']\r\n \r\n # Optional: Default ordering\r\n ordering = ['-created_at']\r\n```\r\n\r\n### 4. Add jqGrid to Your Template\r\n\r\n```html\r\n<!-- Include jQuery and jqGrid files -->\r\n<link rel=\"stylesheet\" href=\"{% static 'django_jqgrid/plugins/jqGrid/css/ui.jqgrid-bootstrap4.css' %}\">\r\n<script src=\"{% static 'django_jqgrid/plugins/jqGrid/js/jquery.jqGrid.min.js' %}\"></script>\r\n<script src=\"{% static 'django_jqgrid/js/jqgrid-integration.js' %}\"></script>\r\n\r\n<!-- Grid Container -->\r\n<table id=\"jqGrid\"></table>\r\n<div id=\"jqGridPager\"></div>\r\n\r\n<script>\r\n$(document).ready(function() {\r\n // Initialize jqGrid with configuration from API\r\n $.getJSON('/api/yourapp/yourmodel/jqgrid_config/', function(config) {\r\n $(\"#jqGrid\").jqGrid(config.jqgrid_options);\r\n \r\n // Apply method options\r\n $(\"#jqGrid\").jqGrid('navGrid', '#jqGridPager', \r\n config.method_options.navGrid.options,\r\n config.method_options.navGrid.editOptions,\r\n config.method_options.navGrid.addOptions,\r\n config.method_options.navGrid.delOptions,\r\n config.method_options.navGrid.searchOptions,\r\n config.method_options.navGrid.viewOptions\r\n );\r\n \r\n // Apply filter toolbar\r\n $(\"#jqGrid\").jqGrid('filterToolbar', config.method_options.filterToolbar.options);\r\n });\r\n});\r\n</script>\r\n```\r\n\r\n## Configuration\r\n\r\n### Serializer-Based Configuration\r\n\r\nThe package automatically configures jqGrid based on your DRF serializer fields:\r\n\r\n```python\r\nfrom rest_framework import serializers\r\nfrom .models import Product\r\n\r\nclass ProductSerializer(serializers.ModelSerializer):\r\n # Read-only fields become non-editable in grid\r\n total_sales = serializers.ReadOnlyField()\r\n \r\n # Custom labels are used in grid headers\r\n name = serializers.CharField(label=\"Product Name\")\r\n \r\n # Field types determine grid column types\r\n price = serializers.DecimalField(max_digits=10, decimal_places=2)\r\n in_stock = serializers.BooleanField()\r\n created_at = serializers.DateTimeField(read_only=True)\r\n \r\n class Meta:\r\n model = Product\r\n fields = ['id', 'name', 'price', 'in_stock', 'total_sales', 'created_at']\r\n```\r\n\r\n### Field Type Mappings\r\n\r\nThe package automatically maps Django field types to jqGrid column configurations:\r\n\r\n| Django Field Type | jqGrid Configuration |\r\n|------------------|---------------------|\r\n| CharField | `stype: 'text'`, search operators: eq, ne, cn, nc, bw, bn, ew, en |\r\n| IntegerField | `stype: 'integer'`, `align: 'right'`, search operators: eq, ne, lt, le, gt, ge |\r\n| DecimalField | `stype: 'number'`, `align: 'right'`, with decimal places |\r\n| BooleanField | `stype: 'checkbox'`, `align: 'center'` |\r\n| DateField | `stype: 'date'`, with datepicker |\r\n| DateTimeField | `stype: 'datetime-local'`, with datetimepicker |\r\n| ForeignKey | `stype: 'select'`, with dropdown data URL |\r\n| EmailField | `stype: 'email'`, `formatter: 'email'` |\r\n| URLField | `stype: 'text'`, `formatter: 'link'` |\r\n\r\n### ViewSet Configuration Options\r\n\r\n```python\r\nclass ProductViewSet(JqGridConfigMixin, JqGridBulkActionMixin, viewsets.ModelViewSet):\r\n queryset = Product.objects.all()\r\n serializer_class = ProductSerializer\r\n \r\n # Column visibility\r\n visible_columns = ['id', 'name', 'price', 'in_stock', 'created_at']\r\n \r\n # Search configuration\r\n search_fields = ['name', 'description', 'sku']\r\n \r\n # Sorting configuration\r\n ordering_fields = ['name', 'price', 'created_at']\r\n ordering = ['-created_at', 'name'] # Default sort\r\n \r\n # Grouping configuration\r\n groupable_fields = ['category', 'brand']\r\n \r\n # Frozen columns (stay visible when scrolling)\r\n frozen_columns = ['id', 'name']\r\n \r\n # Bulk operations\r\n bulk_updateable_fields = ['price', 'in_stock', 'category']\r\n bulk_actions = [\r\n {\r\n 'id': 'bulk-update-price',\r\n 'label': 'Update Price',\r\n 'icon': 'fa-dollar',\r\n 'class': 'btn-warning'\r\n },\r\n {\r\n 'id': 'bulk-delete',\r\n 'label': 'Delete Selected',\r\n 'icon': 'fa-trash',\r\n 'class': 'btn-danger'\r\n }\r\n ]\r\n \r\n # Field overrides\r\n jqgrid_field_overrides = {\r\n 'price': {\r\n 'formatter': 'currency',\r\n 'formatoptions': {'prefix': '$', 'decimalPlaces': 2}\r\n }\r\n }\r\n \r\n # Grid options override\r\n jqgrid_options_override = {\r\n 'rowNum': 50,\r\n 'height': 600,\r\n 'caption': 'Product Inventory'\r\n }\r\n \r\n # Conditional formatting\r\n conditional_formatting = {\r\n 'in_stock': {\r\n 'false': {'color': 'red', 'background': '#ffeeee'},\r\n 'true': {'color': 'green', 'background': '#eeffee'}\r\n },\r\n 'price': {\r\n 'condition': 'value > 1000',\r\n 'style': {'fontWeight': 'bold', 'color': 'blue'}\r\n }\r\n }\r\n```\r\n\r\n## Advanced Features\r\n\r\n### 1. Bulk Operations\r\n\r\nThe `JqGridBulkActionMixin` provides bulk update and delete functionality:\r\n\r\n```javascript\r\n// Bulk update example\r\n$.ajax({\r\n url: '/api/products/bulk_action/',\r\n method: 'POST',\r\n data: JSON.stringify({\r\n ids: [1, 2, 3],\r\n action: {\r\n price: 29.99,\r\n in_stock: true\r\n }\r\n }),\r\n contentType: 'application/json'\r\n});\r\n\r\n// Bulk delete example\r\n$.ajax({\r\n url: '/api/products/bulk_action/',\r\n method: 'POST',\r\n data: JSON.stringify({\r\n ids: [1, 2, 3],\r\n action: {\r\n _delete: true\r\n }\r\n }),\r\n contentType: 'application/json'\r\n});\r\n```\r\n\r\n### 2. Custom Grid Filters\r\n\r\nUsers can save and manage custom grid filters:\r\n\r\n```python\r\n# The package includes GridFilter model for storing user filters\r\nfrom django_jqgrid.models import GridFilter\r\n\r\n# Filters are automatically available in the grid search dialog\r\n# Users can save search criteria as named filters\r\n```\r\n\r\n### 3. Import/Export Configuration\r\n\r\n```python\r\nclass ProductViewSet(JqGridConfigMixin, viewsets.ModelViewSet):\r\n # ... other configuration ...\r\n \r\n import_config = {\r\n 'supported_formats': ['csv', 'xlsx', 'json'],\r\n 'field_mapping': {\r\n 'Product Name': 'name',\r\n 'Price': 'price',\r\n 'Stock': 'in_stock'\r\n }\r\n }\r\n \r\n export_config = {\r\n 'formats': ['csv', 'xlsx', 'pdf'],\r\n 'include_headers': True,\r\n 'max_rows': 10000\r\n }\r\n```\r\n\r\n### 4. Row Grouping\r\n\r\n```python\r\nclass OrderViewSet(JqGridConfigMixin, viewsets.ModelViewSet):\r\n # ... other configuration ...\r\n \r\n groupable_fields = ['status', 'customer', 'date']\r\n aggregation_fields = {\r\n 'total': 'sum',\r\n 'items_count': 'count'\r\n }\r\n```\r\n\r\n## API Endpoints\r\n\r\nThe package automatically creates these endpoints for each model:\r\n\r\n- `GET /api/<app>/<model>/` - List/search records with jqGrid parameters\r\n- `GET /api/<app>/<model>/jqgrid_config/` - Get grid configuration\r\n- `POST /api/<app>/<model>/crud/` - Handle jqGrid CRUD operations\r\n- `POST /api/<app>/<model>/bulk_action/` - Bulk update/delete\r\n- `GET /api/<app>/<model>/dropdown/` - Get dropdown data for foreign keys\r\n\r\n## Settings\r\n\r\n```python\r\n# settings.py\r\n\r\n# Default grid options (optional)\r\nJQGRID_DEFAULT_GRID_OPTIONS = {\r\n 'rowNum': 25,\r\n 'rowList': [25, 50, 100, 500, 1000],\r\n 'height': 400,\r\n 'styleUI': 'Bootstrap4',\r\n 'iconSet': 'fontAwesome'\r\n}\r\n\r\n# Default field type configurations (optional)\r\nJQGRID_DEFAULT_FIELD_CONFIG = {\r\n 'DateField': {\r\n 'formatoptions': {\"srcformat\": \"ISO8601Short\", \"newformat\": \"d/m/Y\"}\r\n }\r\n}\r\n```\r\n\r\n## JavaScript Integration\r\n\r\nThe package includes JavaScript utilities for enhanced functionality:\r\n\r\n```javascript\r\n// jqgrid-integration.js provides helper functions\r\n\r\n// Handle form responses\r\nwindow.handleFormResponse = function(response, postdata) {\r\n // Custom response handling\r\n};\r\n\r\n// Handle export\r\nwindow.handleExport = function() {\r\n // Export grid data\r\n};\r\n\r\n// Handle import\r\nwindow.handleImport = function() {\r\n // Import data dialog\r\n};\r\n```\r\n\r\n## Theme Configuration\r\n\r\nDjango jqGrid supports multiple themes and can be easily customized to match your application's design.\r\n\r\n### Using the Theme Template Tag\r\n\r\n```django\r\n{% load jqgrid_tags %}\r\n\r\n<!-- Use default theme (Bootstrap 4) -->\r\n{% jqgrid_theme %}\r\n\r\n<!-- Specify theme and icon set -->\r\n{% jqgrid_theme 'bootstrap5' 'fontAwesome' %}\r\n\r\n<!-- Use custom CSS -->\r\n{% jqgrid_theme theme='bootstrap4' custom_css='/static/css/my-grid-theme.css' %}\r\n```\r\n\r\n### Available Themes\r\n\r\n- **bootstrap** - Bootstrap 3 theme\r\n- **bootstrap4** - Bootstrap 4 theme (default)\r\n- **bootstrap5** - Bootstrap 5 theme\r\n- **jqueryui** - jQuery UI theme\r\n\r\n### Available Icon Sets\r\n\r\n- **fontAwesome** - Font Awesome icons (default)\r\n- **bootstrap** - Bootstrap Icons\r\n- **jQueryUI** - jQuery UI icons\r\n- **glyph** - Glyphicons (Bootstrap 3)\r\n\r\n### Settings-Based Configuration\r\n\r\nConfigure theme globally in your Django settings:\r\n\r\n```python\r\n# settings.py\r\nJQGRID_THEME = 'bootstrap5'\r\nJQGRID_ICON_SET = 'fontAwesome'\r\nJQGRID_CUSTOM_CSS = '/static/css/custom-grid.css'\r\n```\r\n\r\n### Dynamic Theme Switching\r\n\r\nInclude the theme switcher component:\r\n\r\n```html\r\n<!-- Theme switcher container -->\r\n<div id=\"theme-switcher\"></div>\r\n\r\n<!-- Include theme switcher JS -->\r\n<script src=\"{% static 'django_jqgrid/js/jqgrid-theme-switcher.js' %}\"></script>\r\n\r\n<script>\r\n// Initialize theme switcher\r\njqGridThemeSwitcher.init({\r\n container: '#theme-switcher',\r\n showPreview: true,\r\n onChange: function(theme, iconSet) {\r\n console.log('Theme changed to:', theme, iconSet);\r\n }\r\n});\r\n</script>\r\n```\r\n\r\n### Custom Theme CSS\r\n\r\nCreate your own theme by overriding CSS variables:\r\n\r\n```css\r\n/* custom-grid-theme.css */\r\n:root {\r\n /* Grid colors */\r\n --jqgrid-header-bg: #2c3e50;\r\n --jqgrid-header-text: #ffffff;\r\n --jqgrid-row-hover: #ecf0f1;\r\n --jqgrid-row-selected: #3498db;\r\n \r\n /* Borders */\r\n --jqgrid-border-color: #bdc3c7;\r\n \r\n /* Fonts */\r\n --jqgrid-font-size: 14px;\r\n --jqgrid-header-font-weight: 600;\r\n}\r\n\r\n/* Dark mode support */\r\n@media (prefers-color-scheme: dark) {\r\n :root {\r\n --jqgrid-header-bg: #1a1a1a;\r\n --jqgrid-row-bg: #2a2a2a;\r\n --jqgrid-row-alt-bg: #333333;\r\n }\r\n}\r\n```\r\n\r\n## Customization and Extension\r\n\r\nDjango jqGrid is designed to be highly customizable. Here are some common customization examples:\r\n\r\n### Quick Customization Examples\r\n\r\n#### 1. Custom Formatters\r\n```javascript\r\n// Register a custom status badge formatter\r\nwindow.jqGridConfig.formatters.statusBadge = function(cellval, opts) {\r\n const statusClasses = {\r\n 'active': 'badge-success',\r\n 'pending': 'badge-warning',\r\n 'inactive': 'badge-danger'\r\n };\r\n const badgeClass = statusClasses[cellval] || 'badge-info';\r\n return `<span class=\"badge ${badgeClass}\">${cellval}</span>`;\r\n};\r\n\r\n// Use in ViewSet\r\njqgrid_field_overrides = {\r\n 'status': {\r\n 'formatter': 'statusBadge',\r\n 'align': 'center'\r\n }\r\n}\r\n```\r\n\r\n#### 2. Custom Bulk Actions\r\n```python\r\nclass ProductViewSet(JqGridConfigMixin, JqGridBulkActionMixin, viewsets.ModelViewSet):\r\n # Define custom bulk actions\r\n bulk_actions = [\r\n {\r\n 'id': 'apply-discount',\r\n 'label': 'Apply Discount',\r\n 'icon': 'fa-percent',\r\n 'class': 'btn-warning'\r\n }\r\n ]\r\n \r\n @action(methods=['post'], detail=False)\r\n def bulk_action(self, request):\r\n action_id = request.data.get('action_id')\r\n if action_id == 'apply-discount':\r\n # Custom logic here\r\n return Response({'status': 'success'})\r\n return super().bulk_action(request)\r\n```\r\n\r\n#### 3. JavaScript Hooks\r\n```javascript\r\n// Customize grid behavior using hooks\r\nwindow.jqGridConfig.hooks.beforeInitGrid = function(tableInstance) {\r\n // Add custom configuration before grid initializes\r\n tableInstance.options.customData = { department: 'sales' };\r\n};\r\n\r\nwindow.jqGridConfig.hooks.afterSubmitBulkUpdate = function(tableInstance, ids, action, scope, response) {\r\n // Custom notification after bulk update\r\n showCustomNotification('Updated ' + ids.length + ' records');\r\n};\r\n```\r\n\r\n#### 4. Dynamic Column Configuration\r\n```python\r\nclass UserAwareProductViewSet(JqGridConfigMixin, viewsets.ModelViewSet):\r\n def get_visible_columns(self):\r\n \"\"\"Show different columns based on user permissions\"\"\"\r\n base_columns = ['id', 'name', 'price']\r\n \r\n if self.request.user.has_perm('products.view_cost'):\r\n base_columns.extend(['cost', 'profit_margin'])\r\n \r\n if self.request.user.is_staff:\r\n base_columns.extend(['supplier', 'internal_notes'])\r\n \r\n return base_columns\r\n \r\n def get_jqgrid_config(self, request):\r\n self.visible_columns = self.get_visible_columns()\r\n return super().get_jqgrid_config(request)\r\n```\r\n\r\n#### 5. Custom Toolbar Buttons\r\n```javascript\r\n// Add custom buttons to specific tables\r\nwindow.jqGridConfig.customButtons.product = [\r\n {\r\n id: 'import-csv',\r\n label: 'Import CSV',\r\n icon: 'fa-file-csv',\r\n class: 'btn-success',\r\n action: function(tableInstance) {\r\n showImportModal(tableInstance);\r\n }\r\n }\r\n];\r\n```\r\n\r\n### Complete Customization Guide\r\n\r\nFor comprehensive customization examples including:\r\n- Advanced ViewSet customization\r\n- Custom field types\r\n- Theme customization\r\n- Real-time updates\r\n- Performance optimization\r\n- Complex real-world examples\r\n\r\nSee the [**Customization Guide**](CUSTOMIZATION_GUIDE.md).\r\n\r\n## Example Project\r\n\r\nThe package includes a complete example project demonstrating all features:\r\n\r\n### Running the Example Project\r\n\r\n```bash\r\n# Navigate to example project\r\ncd example_project\r\n\r\n# Install dependencies\r\npip install -r requirements.txt\r\n\r\n# Setup the project\r\npython setup_example.py\r\n\r\n# Run the server\r\npython manage.py runserver\r\n```\r\n\r\nVisit: `http://localhost:8000/`\r\n\r\n## Security\r\n\r\n- All operations respect Django's permission system\r\n- CSRF protection for all POST requests\r\n- User-specific filters are isolated\r\n- Bulk operations validate field permissions\r\n\r\n## Browser Support\r\n\r\n- Chrome (latest)\r\n- Firefox (latest)\r\n- Safari (latest)\r\n- Edge (latest)\r\n- Mobile browsers (responsive mode)\r\n\r\n## Troubleshooting\r\n\r\n### Common Issues\r\n\r\n#### 1. \"jqgrid_tags is not a registered tag library\"\r\n**Solution:**\r\n- Ensure `django_jqgrid` is in your `INSTALLED_APPS`\r\n- Restart the Django development server\r\n- If developing locally, install the package in editable mode: `pip install -e .`\r\n\r\n#### 2. Grid not loading data\r\n**Solution:**\r\n- Check browser console for JavaScript errors\r\n- Verify the API endpoint is accessible\r\n- Ensure DRF permissions allow access\r\n- Check that the ViewSet URL pattern is correct\r\n\r\n#### 3. Bulk operations not working\r\n**Solution:**\r\n- Verify `JqGridBulkActionMixin` is included in your ViewSet\r\n- Check CSRF token is being sent with requests\r\n- Ensure user has appropriate permissions\r\n\r\n#### 4. Custom formatters not displaying\r\n**Solution:**\r\n- Register formatters before grid initialization\r\n- Check formatter function name matches configuration\r\n- Verify no JavaScript errors in formatter function\r\n\r\n#### 5. Performance issues with large datasets\r\n**Solution:**\r\n- Use server-side pagination (enabled by default)\r\n- Add database indexes on frequently sorted/filtered columns\r\n- Use `select_related()` and `prefetch_related()` in querysets\r\n- Consider implementing caching for frequently accessed data\r\n\r\nFor more detailed troubleshooting, see the [Customization Guide](CUSTOMIZATION_GUIDE.md#troubleshooting).\r\n\r\n## Requirements\r\n\r\n- Python 3.8+\r\n- Django 3.2+\r\n- Django REST Framework 3.12+\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License - see the LICENSE file for details.\r\n\r\n## Contributing\r\n\r\nContributions are welcome! Please feel free to submit a Pull Request.\r\n\r\n## Support\r\n\r\nFor issues and feature requests, please use the [GitHub issue tracker](https://github.com/coder-aniket/django-jqgrid/issues).\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Django app for integrating jqGrid with Django REST Framework",
"version": "1.2.7",
"project_urls": {
"Bug Reports": "https://github.com/coder-aniket/django-jqgrid/issues",
"Documentation": "https://django-jqgrid.readthedocs.io",
"Homepage": "https://github.com/coder-aniket/django-jqgrid",
"Source": "https://github.com/coder-aniket/django-jqgrid"
},
"split_keywords": [
"django",
" jqgrid",
" rest",
" framework",
" grid",
" datatable"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "53de5d24d00c7acd0b975241d592b22aa4e2abbff0c01e174ceae0b5a38caf23",
"md5": "234d5a6bd4df5cceadff789a2f387b9b",
"sha256": "08a805afe4ff78134346b80232c49a06b7144f344b29b93f8ca054fa6d5cba33"
},
"downloads": -1,
"filename": "django_jqgrid-1.2.7-py3-none-any.whl",
"has_sig": false,
"md5_digest": "234d5a6bd4df5cceadff789a2f387b9b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 1214284,
"upload_time": "2025-07-22T18:39:34",
"upload_time_iso_8601": "2025-07-22T18:39:34.768036Z",
"url": "https://files.pythonhosted.org/packages/53/de/5d24d00c7acd0b975241d592b22aa4e2abbff0c01e174ceae0b5a38caf23/django_jqgrid-1.2.7-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c462c5d408e16d4d70e92795c08f8196bbf891b520bc7aeef1d8b58a3ac5ee8d",
"md5": "0ba6438aa0fc815644b6e814108fe57e",
"sha256": "d5a3a5a756c8c908ff1a6c731ee872df5985b9bd1754a0cebb66cc0dbbc5400a"
},
"downloads": -1,
"filename": "django_jqgrid-1.2.7.tar.gz",
"has_sig": false,
"md5_digest": "0ba6438aa0fc815644b6e814108fe57e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 1113510,
"upload_time": "2025-07-22T18:39:38",
"upload_time_iso_8601": "2025-07-22T18:39:38.292251Z",
"url": "https://files.pythonhosted.org/packages/c4/62/c5d408e16d4d70e92795c08f8196bbf891b520bc7aeef1d8b58a3ac5ee8d/django_jqgrid-1.2.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-22 18:39:38",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "coder-aniket",
"github_project": "django-jqgrid",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "Django",
"specs": [
[
">=",
"3.2"
],
[
"<",
"5.0"
]
]
},
{
"name": "djangorestframework",
"specs": [
[
">=",
"3.12.0"
]
]
},
{
"name": "django-filter",
"specs": [
[
">=",
"21.1"
]
]
}
],
"lcname": "django-jqgrid"
}