0

So I have a Django ListView that looks like

class FirePageView(ListView):
    model = MyModel
    template_name = 'page.html'
    context_object_name = 'my_list'
    ordering = ['-timestamp']

So can I render a table just fine and everything is working there. However, I want to apply a transformation, for example changing all the timestamps from UTC to EST before sending it to the template. This way the template shows the times in EST but not UTC. How can I edit what the ListView passes into the template?

kauii8
  • 199
  • 9
  • 2
    That is something you should apply on the template, maybe with a [custom filter](https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/#writing-custom-template-filters). – Klaus D. Sep 22 '20 at 07:34
  • 1
    Comments from [this](https://stackoverflow.com/questions/34803906/utc-to-local-timezone-in-a-flask-jinja-template) post may help you, so take a look. – Maran Sowthri Sep 22 '20 at 08:04
  • 1
    Regarding the transformation of timestamps: If you use the internationalization features of django, all timestamps which are UTC in the database get transformed to your local format anyway! So if you activated localization and internationalization, you don't need to do anything. – Yves Hary Sep 22 '20 at 08:25

2 Answers2

2

Like the other authors said, your specific use case (transforming timestamps) would be solved best by a template tag.

If you still want to modify your data, have a look into djangos MultipleObjectMixin which gets used in djangos ListView:

class MultipleObjectMixin(ContextMixin):
    """A mixin for views manipulating multiple objects."""
    allow_empty = True
    queryset = None
    model = None
    paginate_by = None
    paginate_orphans = 0
    context_object_name = None
    paginator_class = Paginator
    page_kwarg = 'page'
    ordering = None

    def get_queryset(self): # YOU CAN OVERRIDE THIS METHOD FOR YOUR USE
        """
        Return the list of items for this view.

        The return value must be an iterable and may be an instance of
        `QuerySet` in which case `QuerySet` specific behavior will be enabled.
        """
        if self.queryset is not None:
            queryset = self.queryset
            if isinstance(queryset, QuerySet):
                queryset = queryset.all()
        elif self.model is not None:
            queryset = self.model._default_manager.all()
        else:
            raise ImproperlyConfigured(
                "%(cls)s is missing a QuerySet. Define "
                "%(cls)s.model, %(cls)s.queryset, or override "
                "%(cls)s.get_queryset()." % {
                    'cls': self.__class__.__name__
                }
            )
        ordering = self.get_ordering()
        if ordering:
            if isinstance(ordering, str):
                ordering = (ordering,)
            queryset = queryset.order_by(*ordering)

        return queryset

You can hook into the get_queryset() method and return an iterable which is transformed the way you want it. With using this hook you can still use all benefits of the generic ListView.

Yves Hary
  • 302
  • 1
  • 9
0

Thanks for your comments and answers everyone. If you are interested in directly editing the queryset which is probably useful in it's own right please take a look below at @Yves Hary's answer.

For my usecase, a custom template tag (https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/#writing-custom-template-filters) works. If you are interested this is my code:

In app/templatetags/timezone_conversion.py

import pytz

from django import template

register = template.Library()

@register.filter(name='timezone_conversion_filter')
def timezone_conversion_filter(time, timezone):
    tz = pytz.timezone(timezone)
    print(time, tz, )
    local_dt = time.astimezone(tz)
    print(time, tz)

    return local_dt.strftime("%b %e, %Y, %I:%M %p")

Then in your html page

{% load timezone_conversion %}

{{ your_datetime|timezone_conversion_filter:"US/Pacific" }}
kauii8
  • 199
  • 9