Search code examples
pythondjangosql-order-by

Django users last login = NULL ordered in different way between local and production


I have this ListView which returns a list of users ordered by last_login.

class ListaUtentiOrderedByLastLogin(StaffRequiredMixin, ListView):
   model = EmailUser
   context_object_name = "lista_utenti"
   template_name = "emailusers/lista_utenti.html"
   paginate_by = settings.PAGINATION_NUM

   def get_queryset(self):
      if self.kwargs['order'] == "asc":
         return EmailUser.objects.order_by('last_login',Upper('last_name'), Upper('first_name'), Upper('email'))
      else:
         return EmailUser.objects.order_by('-last_login',Upper('last_name'), Upper('first_name'), Upper('email'))

Locally users are ordered with last_login NULL < NOT_NULL so in descending case users not yet logged are at the bottom of the user list. But in production NULL > NOT_NULL and same users are at the top of the list.

Locally I use squlite db and the webserver included in manage.py Production: postgresql + gunicorn + nginx


Solution

  • You can specify how to order with nulls_first=True or nulls_last=True with .asc(…) [Django-doc] or .desc(…) [Django-doc], for example:

    from django.db.models import F
    
    return EmailUser.objects.order_by(
        F('last_login').asc(nulls_last=True),Upper('last_name'), Upper('first_name'), Upper('email')
    )

    this will add a clause that looks like:

    ORDER BY last_login IS NOT NULL, last_login, …

    and thus force nulls to be placed last.