Django REST Pandas
Django REST Pandas

Configuration

URL Configuration #

To use Django REST Pandas in your project, you will generally need to define an API view and register it with urls.py as shown below:

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

urlpatterns = (
    path("data", TimeSeriesView.as_view()),
)

# The following is required to support extension-style formats (e.g. /data.csv)
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = format_suffix_patterns(urlpatterns)

When using DRP with the wq framework, you can instead register a PandasViewSet subclass with wq.db.rest.router. wq.db provides extension-style formats by default.

from wq.db import rest
from .views import TimeSeriesViewSet

rest.router.add_page(
    "data",
    {
        "url": "data",
        "template": "table",
        "table": {"url": "/data.csv"},
    },
    TimeSeriesViewSet,
)
Customizing Renderers #

DRP provides a set of default renderers that you can oveeride by setting REST_PANDAS["RENDERERS"] in your settings.py, or by overriding renderer_classes in your individual view(s). REST_PANDAS["RENDERERS"] should be a list or tuple of string paths pointing to one or more Django REST Framework renderer classes.

The default REST_PANDAS["RENDERERS"] setting is as follows:

REST_PANDAS = {
    "RENDERERS": (
        "rest_pandas.renderers.PandasHTMLRenderer",
        "rest_pandas.renderers.PandasCSVRenderer",
        "rest_pandas.renderers.PandasTextRenderer",
        "rest_pandas.renderers.PandasJSONRenderer",
        "rest_pandas.renderers.PandasExcelRenderer",
        "rest_pandas.renderers.PandasOldExcelRenderer",
        "rest_pandas.renderers.PandasPNGRenderer",
        "rest_pandas.renderers.PandasSVGRenderer",
    ),
)

When using DRP with the wq framework, "rest_pandas.renderers.PandasHTMLRenderer" is automatically replaced with "wq.db.rest.renderers.HTMLRenderer" by default.

REST_PANDAS["RENDERERS"] is similar to Django REST Framework's own DEFAULT_RENDERER_CLASSES setting, but defined separately in case you plan to have DRP-enabled views intermingled with regular DRF views. That said, it is also possible to include DRP renderers in DEFAULT_RENDERER_CLASSES. To do so, extend PandasMixin in you view or set Meta.list_serializer_class explicitly on your serializer. Otherwise, you may get an error saying the serializer output is not a DataFrame.

In short, there are three paths to getting DRP renderers working with your views:

  1. Extend PandasView, PandasSimpleView, or PandasViewSet, and use the PANDAS_RENDERERS setting (which defaults to the list above).
  2. Extend PandasMixin and customize REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES'] to add one or more rest_pandas renderers.
  3. Set renderer_classes explicitly on the view, and set Serializer.Meta.list_serializer_class to PandasSerializer or a subclass. (See #32 and #36 for examples.)
class TimeSeriesView(PandasView):
    # renderer_classes default to PANDAS_RENDERERS
    ...

class TimeSeriesView(PandasMixin, ListAPIView):
    # renderer_classes default to REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES']
    ...
Field Labels #

By default, Django REST Pandas will update the dataframe columns to use the label attribute of defined serializer fields, and/or the verbose_name attribute of any underlying model fields. To disable this functionality (and use the field names as column names), set REST_PANDAS["APPLY_FIELD_LABELS"] to false.

REST_PANDAS = {
    "APPLY_FIELD_LABELS": True,  # Default in DRP 2.0
}

REST_PANDAS = {
    "APPLY_FIELD_LABELS": False,  # Compatible with DRP 1.x
}
Date Formatting #

By default, Django REST Framework will serialize dates as strings before they are processed by the renderer classes. In many cases, you may want to preserve the dates as datetime objects and let Pandas handle the rendering. To do this, define an explicit DateTimeField or DateField on your DRF serializer and set format=None:

# serializers.py
class TimeSeriesSerializer(serializers.ModelSerializer):
    date = serializers.DateField(format=None)
    class Meta:
        model = TimeSeries
        fields = '__all__'

Alternately, you can disable date serialization globally by setting DATETIME_FORMAT and/or DATE_FORMAT to None in your settings.py:

# settings.py
DATE_FORMAT = None
© 2014-2024 by S. Andrew Sheppard