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.1.tar.gz (7.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.1-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for drf_csv_renderer-0.1.1.tar.gz
Algorithm Hash digest
SHA256 bc6d8382190c619a7104678386e8a03157ee8635d74caea3ffe22cd6f666dbf0
MD5 ac8444c1a06696e21eda22b14ec76c0a
BLAKE2b-256 d2ea957fca428361207802283861e0bbf63359fe6bef207821e04da6cfd3ab2e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for drf_csv_renderer-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0384e28c310cac44994ed9f5a241f4852bd8784913c9dac59602de324b215e57
MD5 a8d81712af6d0de68906d001755ddbc5
BLAKE2b-256 d021fa7ee31e0203b376a91ff440f51cc48491f59bfc90621cbe9567ff6b6182

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