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
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())