Skip to main content

Django REST Framework CSV renderer with configurable field flattening

Project description

Django REST Framework CSV Renderer

A powerful and flexible CSV renderer library for Django REST Framework that provides both standard and streaming CSV export capabilities with advanced data flattening and configuration options.

Features

  • Standard & Streaming CSV Export: Choose between complete data loading or memory-efficient streaming
  • Smart Data Flattening: Automatically flatten nested objects and relationships
  • List Preservation: Keep lists as JSON arrays or convert to comma-separated strings
  • True Streaming: Process large datasets without loading everything into memory
  • Flexible Configuration: Extensive customization options for CSV output
  • DRF Integration: Seamlessly integrates with existing DRF views and serializers
  • QuerySet Optimization: Uses Django's iterator() for memory-efficient database queries

Installation

pip install drf-csv-renderer

Quick Start

Basic Usage

# views.py
from drf_csv_renderer.views import CSVListView
from .models import User
from .serializers import UserSerializer

class UserCSVExportView(CSVListView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    csv_filename = 'users.csv'

Streaming for Large Datasets

class UserStreamingCSVView(CSVListView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    csv_filename = 'users_stream.csv'
    csv_streaming = True  # Enable true streaming

Configuration Options

Option Default Description
csv_filename None Custom filename for CSV download
csv_streaming False Enable streaming response for large datasets
csv_flatten_nested True Flatten nested objects and relationships
csv_preserve_lists True Keep lists as JSON arrays vs comma-separated strings
csv_nested_separator '__' Separator for flattened nested field names
csv_writer_options {} Additional options for Python's csv.DictWriter

Advanced Usage

Custom CSV Configuration

class ConfiguredCSVView(CSVListView):
    queryset = User.objects.select_related('profile')
    serializer_class = UserDetailSerializer
    
    # CSV Configuration
    csv_filename = 'detailed_users.csv'
    csv_streaming = True
    csv_flatten_nested = True
    csv_preserve_lists = False  # Convert lists to "item1, item2"
    csv_nested_separator = '.'  # Use dots instead of underscores
    csv_writer_options = {
        'delimiter': ';',
        'quotechar': '"',
        'quoting': csv.QUOTE_MINIMAL
    }

Custom Data Processing

from drf_csv_renderer.views import CSVGenericView

class CustomReportCSVView(CSVGenericView):
    csv_filename = 'custom_report.csv'
    csv_streaming = True
    
    def get_csv_data(self):
        # Return a generator for memory-efficient streaming
        def data_generator():
            for user in User.objects.iterator():
                yield {
                    'user_id': user.id,
                    'username': user.username,
                    'profile': {
                        'phone': user.profile.phone,
                        'bio': user.profile.bio
                    },
                    'tags': ['admin', 'active'],  # Preserved as JSON array
                    'created_at': user.date_joined
                }
        return data_generator()

Data Flattening Examples

Nested Objects

Input:

{
    'user': {
        'name': 'John Doe',
        'profile': {
            'phone': '+1234567890',
            'address': {
                'city': 'New York',
                'country': 'USA'
            }
        }
    }
}

CSV Output (with csv_nested_separator='__'):

user__name,user__profile__phone,user__profile__address__city,user__profile__address__country
John Doe,+1234567890,New York,USA

List Handling

Input:

{
    'username': 'john_doe',
    'tags': ['admin', 'developer', 'active'],
    'permissions': ['read', 'write', 'delete']
}

With csv_preserve_lists=True (default):

username,tags,permissions
john_doe,"[""admin"", ""developer"", ""active""]","[""read"", ""write"", ""delete""]"

With csv_preserve_lists=False:

username,tags,permissions
john_doe,"admin, developer, active","read, write, delete"

Performance Considerations

Memory Usage

  • Standard Mode: Loads all data into memory - suitable for smaller datasets
  • Streaming Mode: Processes one record at a time - ideal for large datasets

Database Optimization

class OptimizedCSVView(CSVListView):
    # Use select_related for foreign keys to reduce queries
    queryset = User.objects.select_related('profile', 'department')
    
    # Use prefetch_related for many-to-many and reverse foreign keys
    # queryset = User.objects.prefetch_related('groups', 'user_permissions')
    
    csv_streaming = True  # Enable streaming for large datasets

URL Configuration

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    # Standard CSV export
    path('users/export/', views.UserCSVExportView.as_view(), name='users-csv'),
    
    # Streaming CSV export
    path('users/export/stream/', views.UserStreamingCSVView.as_view(), name='users-csv-stream'),
    
    # Custom CSV report
    path('reports/custom/', views.CustomReportCSVView.as_view(), name='custom-csv'),
]

Integration with DRF Features

Filtering and Pagination

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter

class FilteredCSVView(CSVListView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    
    # DRF filtering works automatically
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['is_active', 'date_joined']
    search_fields = ['username', 'email']
    ordering_fields = ['date_joined', 'username']
    
    # Pagination is automatically handled for non-streaming responses
    csv_streaming = False  # Respects pagination
    # csv_streaming = True   # Ignores pagination for full dataset

Permissions and Authentication

from rest_framework.permissions import IsAuthenticated

class SecureCSVView(CSVListView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated]  # Standard DRF permissions
    csv_filename = 'secure_users.csv'

Response Headers

The library automatically sets appropriate headers for CSV downloads:

Content-Type: text/csv; charset=utf-8
Content-Disposition: attachment; filename="users.csv"

For streaming responses, the Transfer-Encoding: chunked header is automatically added.

Error Handling

class RobustCSVView(CSVListView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    
    def get_csv_data(self):
        try:
            return super().get_csv_data()
        except Exception as e:
            # Log error and return empty dataset or handle gracefully
            logger.error(f"CSV export error: {e}")
            return []

Best Practices

  1. Use streaming for large datasets (>10k records)
  2. Optimize database queries with select_related() and prefetch_related()
  3. Set appropriate timeouts for large exports
  4. Consider background tasks for very large datasets using Celery
  5. Test memory usage with realistic data volumes
  6. Use meaningful filenames with timestamps if needed

Requirements

  • Python 3.7+
  • Django 3.2+
  • Django REST Framework 3.12+

License

MIT License

Contributing

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

Changelog

v1.0.0

  • Initial release
  • Standard and streaming CSV export
  • Data flattening with configurable options
  • List preservation options
  • Full DRF integration

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drf_csv_renderer-0.1.4.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

drf_csv_renderer-0.1.4-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file drf_csv_renderer-0.1.4.tar.gz.

File metadata

  • Download URL: drf_csv_renderer-0.1.4.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.1

File hashes

Hashes for drf_csv_renderer-0.1.4.tar.gz
Algorithm Hash digest
SHA256 2fc1541cbe344f0c54c6f2bb8f0e86069870423b946c100209607bb1c672c779
MD5 12414fbdee63ab01621473807caf9aff
BLAKE2b-256 eb985f34863a22e023f2c6d36e5dbeea4548bd62d7a3834fc274f82477f83f97

See more details on using hashes here.

File details

Details for the file drf_csv_renderer-0.1.4-py3-none-any.whl.

File metadata

File hashes

Hashes for drf_csv_renderer-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 5c8e94bb8f59cc1265ca89d71657f4e1ea366769287a046d6242be50f8b997a0
MD5 f5785f95be5cb149d0e18691b663e70b
BLAKE2b-256 9e3de5592730e9b6f6d0f4492b8ff9fdb9e7e6249b8c21a52933d37c40192282

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page