Django 1.5 - Python 2.7 - TIME_ZONE does not set correctly ( from custom user field ) upon login, until after first page reload

StackOverflow https://stackoverflow.com/questions/18633914

Question

My issue is that I have setup custom user timezone settings in Django, and that it only correctly sets the TIME_ZONE value after the first page reload. Currently, if a user logs in, he sees the default TIME_ZONE setting ( 'America/New_York' ), and then upon first refresh sees his own timezone setting correctly (I.E. - 'America/Vancouver' ).

Here is my Middleware

from django.utils import timezone

class TimezoneMiddleware(object):
    def process_request(self, request):
        tz = request.session.get('django_timezone')
        if tz:
            timezone.activate(tz)

Here is my login view, which uses pytz to evaluate the string timezone taken from the user in the database, and puts it in the session. After initial login, the timezone isn't being reflected by TIME_ZONE. If I have {{TIME_ZONE}} in my template, it shows as 'America/New_York', the default setting. After a single page refresh, it then shows as 'America/Vancouver', the user's setting.

def login_view(request):
    if request.method == 'POST':
        user = authenticate(username=request.POST['username'], password=request.POST['password'])

        if user is not None:

            if user.is_active:
                login(request, user)
                request.session['user'] = user
                userdetails = user.get_profile()
                request.session['django_timezone'] = pytz.timezone(userdetails.timezone)
                # Prioritize favorite company in index list of companies
                return companyHome(request, userdetails.get_favorite_company_id())

Here is my form in my timezone submit template, it works as expected and sets the timezone upon use.

  <form action="{% url 'onBaristaApp:set_timezone' %}" method="POST">
      {% csrf_token %}
      <label for="timezone">Time zone:</label>
      <select name="timezone">
          {% for tz in timezones %}
          <option value="{{ tz }}"{% if tz == TIME_ZONE %} selected="selected"{% endif %}>{{ tz }}</option>
          {% endfor %}
      </select>
      <input type="submit" value="Set" />
  </form>

Here is the view associated with it.

def set_timezone(request):
    user = ViewManager.login_handler(request)

    if request.method == 'POST':
        new_timezone = pytz.timezone(request.POST['timezone'])
        request.session['django_timezone'] = new_timezone
        userdetails = user.get_profile()
        userdetails.timezone = new_timezone
        userdetails.save()
        return redirect('/Profile/')

    else:
        return render(request, 'login.html')

Here is the relevant model field on the custom user profile

class UserProfile(models.Model):
    ...
    timezone = models.CharField(max_length=50, default='America/New_York')
    ...

Here is the template where the issue occurs

{% extends "base.html" %}
{% load url from future %}
{% load tz %}
{% get_current_timezone as TIME_ZONE %}

{% block body_tag %} home {% endblock %}

{% block contents %}

...
          {% for check_in_object in location.get_checkins %}
              {% localtime on %}
              ...
                      {{ check_in_object }}{{ check_in_object.get_tzobject }}
              ...

              {% endlocaltime %}
          ...
{% endblock %}

Here is the code for the method get_tzobject which shows the time, as well as the model and fields

class checkIn(models.Model):
    ...
    inTime = models.DateTimeField(null=True)
    outTime = models.DateTimeField(null=True)
    checkedin = models.BooleanField(default=True)
    ...

    def get_tzobject(self):
        if self.checkedin:
            timezone_corrected_time = localtime(self.inTime)
        else:
            timezone_corrected_time = localtime(self.outTime)

        activate(timezone_corrected_time.tzinfo)
        return timezone_corrected_time
Was it helpful?

Solution

I was able to fix this by adding timezone.activate(pytz.timezone(userdetails.timezone)) in my login_view code.

def login_view(request):
    if request.method == 'POST':
        user = authenticate(username=request.POST['username'],     password=request.POST['password'])

        if user is not None:

            if user.is_active:
                login(request, user)
                request.session['user'] = user
                userdetails = user.get_profile()
                timezone.activate(pytz.timezone(userdetails.timezone))
                request.session['django_timezone'] = pytz.timezone(userdetails.timezone)
                # Prioritize favorite company in index list of companies
                return companyHome(request, userdetails.get_favorite_company_id())
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top