30 Jul 2025

feedDjango community aggregator: Community blog posts

Django: split ModelAdmin.get_queryset() by view

Within Django's popular admin site, you can override ModelAdmin.get_queryset() to customize the queryset used by the admin views. It's often used for performance optimizations, such as adding a select_related() call to batch-fetch related objects:

from django.contrib import admin

from example.models import Book


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        return super().get_queryset(request).select_related("author")

However, one thing this approach lacks is granularity-the queryset returned by get_queryset() is used for all admin views, such as the change list, change form, and any custom views that you might add. That can mean that adding an optimization in get_queryset() for one view can impose a performance cost on other views that don't need it. For example, the above select_related() call might optimize showing author details shown on the change list view, but other pages that don't show the author will still incur the cost of the join.

There isn't an easy way to customize the queryset for individual views without overriding a lot of their code. However, the queryset() method is passed the current request object as context, which allows you to differentiate between views based on request.resolver_match. I think the most robust way to check the current admin view from there is with the __name__ attribute of the func:

from django.contrib import admin

from example.models import Book


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        queryset = super().get_queryset(request)

        if request.resolver_match.func.__name__ == "changelist_view":
            queryset = queryset.select_related("author")

        return queryset

request.resolver_match.func is the current view function, which will be a method of the current ModelAdmin instance, wrapped with the AdminSite.admin_view decorator. Its __name__ attribute gives the name of the view function, which you can use to differentiate between views. For the built-in admin views, it will be one of the following:

(add_view is not included here as it does not call get_queryset().)

Fin

May your admin views run swift and true,

-Adam

30 Jul 2025 4:00am GMT

29 Jul 2025

feedDjango community aggregator: Community blog posts

Our tools are still not designed for the AI future

First a disclaimer on this one: I am making the assumption that the AI trend is here to stay in some form and an economic crash/bubble doesn't make the usage of them untenable, also I have yet experiment with every tool out there!

With that said, a brief personal history of my usage of LLM's and the current wave of AI. I tried out ChatGPT when it was first released and was fairly impressed by the results, but the cruical missing step for me was the lack of browser integration, searching Google was still much quicker from a new tab page and the results from ChatGPT felt isolated, there was too much friction in my workflow for it be usable. I tried out a different product (I forget the name), which allowed me to search from a new tab page and I got AI results and normal search results in one go. This was better, but it still didn't stick, and so I kept experimenting with the tools on an ad-hoc basis, solving small challenges, but it not being a daily driver. In this I experimented with local LLMs and Zed's AI integration.

This changed earlier this year where I experimented with Manus.im and using Claude with Zed's agent mode. Both of these unlocked ideas or wrote decent code directly into my project for me to review, saving me time that I could measure. Since then I have used Zed's agent mode more frequently, that said I do still enjoy coding myself so sometimes forget to use the tools available.

This daily to weekly usage has led me to consider what an AI-first IDE would look like. At this point the newly released Kiro or Cursor comes to mind or others such as Zed or VSCode plus extensions, they are all really designed for a developer-first point of view since their beginning's were from a time before agent workflows existed.

Personally I am looking forward to the IDE that is built ground up to create, run and manage agents that follows the trend of 'spec-driven-development' that has started to form recently within AI circles. Generally I would expect the following:

Is this something of a wishlist? Yes, but I could easily a version of this starting soon, because there a paradigm shift coming I think, where the day to day activity goes from one of writing on our local machines, to one of review on our local machines being the priority. Let me know what you think!

29 Jul 2025 5:00am GMT

28 Jul 2025

feedDjango community aggregator: Community blog posts

User Timezones in Django

When you create a local website, the local time usually matches your country's timezone, and all visitors see times in that timezone. That's not a big issue if your country has only one timezone and your audience is local.

But when building a social platform like pybazaar.com, users are international and need to see times in their timezones. In this article, I'll show you how to handle that in Django.

Time Zone Database

Since version 4.0, Django has used the zoneinfo library for managing timezones, and it used pytz up to version 3.2. Both rely on the IANA Time Zone Database (tzdata). IANA is the same organization that manages the DNS root zone, IP addresses, and other global internet resources.

Install tzdata in your virtual environment as usual:

(venv)$ pip install --upgrade tzdata

Timezone Changes

Timezone information changes several times a year due to:

  1. Daylight Saving Time (DST) adjustments
  2. Political and border changes
  3. Shifts in standard time offset

Daylight Saving Time (DST) was first introduced in 1914 in Canada and later standardized in the U.S. in 1966. When dealing with historic dates before 1966-or future dates with uncertain timezone rules-precise time calculations can be unreliable.

# Before U.S. DST standardization:
old_date = datetime(1960, 6, 15, 12, 0)  

# DST rules may change in the future:
future_date = datetime(2030, 6, 15, 12, 0) 

Some timezone changes are driven by politics:

And countries sometimes adjust their UTC offsets:

Best Practices for Django

Timezone Management for a Social Platform

For platforms with global users:

1. Enable Timezone Support in Django Settings

Set the default timezone to UTC:

# settings.py
USE_TZ = True
TIME_ZONE = "UTC"  # Store everything in UTC

2. Add a timezone Field to the Custom User Model

Use a function for dynamic timezone choices, so you don't need new migrations when the list changes.

def get_timezone_choices():
    import zoneinfo
    return [(tz, tz) for tz in sorted(zoneinfo.available_timezones())]

class User(AbstractUser):
    # ...
    timezone = models.CharField(
        _("Timezone"), max_length=50, choices=get_timezone_choices, default="UTC"
    )

3. Detect Timezone on the Frontend

Add hidden fields in your Login and Signup forms to capture the user's timezone from their browser:

document.addEventListener('DOMContentLoaded', function () {
    const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
    const timezoneInput = document.getElementById('id_timezone');
    if (timezoneInput) {
        timezoneInput.value = userTimezone;
    }
});

You can also let users change their timezone manually in account settings.

4. Use a Custom DateTime Field in Forms

This field will convert datetimes between UTC and the user's local timezone:

import datetime
from zoneinfo import ZoneInfo
from django import forms
from django.utils import timezone
from django.utils.dateparse import parse_datetime

class TimezoneAwareDateTimeField(forms.DateTimeField):
    widget = forms.DateTimeInput(attrs={"type": "datetime-local"})

    def __init__(self, user_timezone=None, *args, **kwargs):
        self.user_timezone = user_timezone
        super().__init__(*args, **kwargs)

    def prepare_value(self, value):
        if value and self.user_timezone:
            try:
                user_tz = ZoneInfo(self.user_timezone)
                if timezone.is_aware(value):
                    value = value.astimezone(user_tz)
            except Exception:
                pass
        return value

    def to_python(self, value):
        if value in self.empty_values:
            return None
        if isinstance(value, datetime.datetime):
            result = value
        elif isinstance(value, datetime.date):
            result = datetime.datetime(value.year, value.month, value.day)
        else:
            try:
                result = parse_datetime(value.strip())
            except ValueError:
                raise forms.ValidationError(
                    self.error_messages["invalid"], code="invalid"
                )
        if not result:
            result = super(forms.DateTimeField).to_python(value)
        if result and self.user_timezone:
            try:
                user_tz = ZoneInfo(self.user_timezone)
                if timezone.is_naive(result):
                    result = result.replace(tzinfo=user_tz)
                result = result.astimezone(ZoneInfo("UTC"))
            except Exception:
                pass
        return result

The type="datetime-local" widget uses the browser's native date/time picker.

Use the custom field like this:

from django import forms
from django.utils.translation import gettext_lazy as _
from myproject.apps.core.form_fields import TimezoneAwareDateTimeField
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ["title", "content", "published_from"]

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request
        self.fields["published_from"] = TimezoneAwareDateTimeField(
            label=_("Published from"),
            help_text=_("Enter date and time in your local timezone."),
            required=False,
            user_timezone=self.request.user.timezone,
        )

5. Output Dates and Times in User's Timezone

{% load tz %}
{% with user_timezone=request.user.timezone|default:"UTC" %}
    {{ post.published_from|timezone:user_timezone|date:"j M, Y H:i" }}
{% endwith %}

Other Options

You can also detect the visitor's timezone in JavaScript and send it via Ajax to be saved in the Django session. Then you can use it even for anonymous users.

Final Words

Timezones aren't so scary if you follow Django's best practices:

This keeps your website accurate, user-friendly, and ready for global audiences.


Cover photo by Andrey Grushnikov

28 Jul 2025 5:00pm GMT