I have the below settings:
TIME_ZONE = UTC
USE_TZ = True
My server timezone is UTC+1 and the end user's timezone is UTC+2. Should I care about the server timezone or it is not related at all?
Server time zone isn't related in most cases. Your application will use UTC. The most common application in python uses datetime.datetime.now(tzInfo=None) which will automatically pass tzInfo as None when you call datetime.datetime.now() . Unless you specify what timezone tzInfo is, the datetime object will always return UTC.
Related
Before marked as dup (I believe many answers are incorrect becase):
According to my research:
request.session.get_expiry_age returns the TOTAL lifespan of the cookie, not the time from now until it expires. It always returns the same value, irrespecitive of how much time is left.
Similarly get_expiry_date adds the total lifespan to the now time. It always increases when called.
Hence niether of them help.
settings.SESSION_SAVE_EVERY_REQUEST refreshes the cookie on every request, this is NOT what I am trying to achieve.
get_session_cookie_age() ONLY returns the value of settings.SESSION_COOKIE_AGE, as seen in the sourcecode:
def get_session_cookie_age(self):
return settings.SESSION_COOKIE_AGE
I use the cached_db session back end. The cached part is made none in void because it has to save the cookie everytime, hence SESSION_SAVE_EVERY_REQUEST is not applicable. The reason I ask this question is because I wish to refresh a cookie ONLY if the time left has gone below a threshold, and hence have some hysterious (have the benefits of caching and auto refreshing).
Here is my code that does not work because of the behaviour of get_expiry_age/get_expiry_date as explained above:
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
class SessionExpiry(MiddlewareMixin):
def process_request(self, request):
"""Automatically refresh a session expirary at a certain limit.
If request.session age goes below settings.SESSION_REFRESH, then
set the sessions expirary age to settings.SESSION_COOKIE_AGE. The
session is not refreshed every time to have the caching benefits of
the cached_db backend.
"""
try:
empty = request.session.is_empty()
except AttributeError:
return None
if (empty or not getattr(settings, 'SESSION_REFRESH', None)):
return None
if request.session.get_expiry_age() < settings.SESSION_REFRESH:
request.session.set_expiry(settings.SESSION_COOKIE_AGE)
return None
This is an area of Django that's confusing, in both design and documentation. The easiest way to figure out what's going on is to look at the source code.
To get what you want you need to set a custom expiration as a datetime. If you use seconds (including the default SESSION_COOKIE_AGE) that is interpreted as the number of seconds from now; that is, from whenever you ask.
So to set the expiration, use:
# Using timedelta will cause the session to save the expiration time as a datetime.
request.session.set_expiry(timedelta(seconds=settings.SESSION_COOKIE_AGE))
If you do that, calls to get_expiry_age() will return the actual difference between the current datetime and the datetime set as the expiry.
Be sure to note the warning in the set_expiry() documentation: "Note that datetime and timedelta values are only serializable if you are using the PickleSerializer."
Came here from the Django ticket. Here is what I came up with avoiding the need for pickle serializer and SESSION_SAVE_EVERY_REQUEST. So instead of using the datetime we can use plain timestamp, and since set_expire does not support that, we will just add another session key to store that.
class RefreshSessionMiddleware(middleware.SessionMiddleware):
def process_response(self, request, response):
session = request.session
if not (session.is_empty() or session.get_expire_at_browser_close()):
expiry = session.get('_session_expire_at_ts')
now_ts = int(time.time())
cookie_lifetime = session.get_expiry_age()
if expiry is None or now_ts + cookie_lifetime / 2 > expiry:
# This will set modified flag and update the cookie expiration time
session['_session_expire_at_ts'] = now_ts + cookie_lifetime
return super().process_response(request, response)
Remember-me is
a parameter
flask_login.login_user(user, remember=False, duration=None, force=False, fresh=True)
to login_user in Flask-Login. It makes it possible "to remember the user after their session expires."
And yet with just Flask (and not Flask-Login)
'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31)
is set by default to 31 days in the default_config (and it can be suitably modified).
Also session.permanent can be set to make a session permanent,
perhaps through:
from datetime import timedelta
from flask import session, app
#app.before_request
def make_session_permanent():
session.permanent = True
app.permanent_session_lifetime = timedelta(minutes=5)
Does Flask-Login's remember_me override Flask's permanent? How do they interact?
remember_me is not stored in the Flask session. It is is stored in a separate cookie who's name and expiration is handled in the Flask-Login configuration:
REMEMBER_COOKIE_NAME
The name of the cookie to store the “remember me” information in. Default: remember_token
REMEMBER_COOKIE_DURATION
The amount of time before the cookie expires, as a datetime.timedelta object or integer seconds. Default: 365 days (1 non-leap Gregorian year)
REMEMBER_COOKIE_REFRESH_EACH_REQUEST
If set to True the cookie is refreshed on every request, which bumps the lifetime. Works like Flask’s SESSION_REFRESH_EACH_REQUEST. Default: False
plus a few more REMEMBER_COOKIE_* settings to control visibility of the cookie (domain, path, encrypted connections only, and if code running in the browser can access the value).
The Flask session configuration has no bearing on this; that's a separate cookie with separate settings. The remember me functionality does not interact with Flask's permanent_session_lifetime / PERMANENT_SESSION_LIFETIME setting, the Flask SESSION_COOKIE_* configuration, or app.session.permanent, at all.
By default, Flask uses session as the session cookie name, and Flask-Login uses remember_token for the remember me cookie.
Beginner Django programmer here. I'm working on a Django app and am having timezone issues. My code successfully converts time objects into local time when I run on my local server but this conversion does not work when my application is hosted on Heroku.
I am currently converting timezone using the tzlocal extension. In my views I use the code:
activate(get_localzone())
On my local server, get_localzone() successfully returns the local time. On the Heroku-hosted version of my application, get_localzone() returns UTC.
Here are my time settings in settings.py:
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
Not sure if this matters but I'm using a Postgres database:
DATABASES = {'default': dj_database_url.config(default='postgres://localhost')}
Here is an example of my home view to give you a sense of how I'm using the tzlocal package:
def home(request):
if not request.user.is_authenticated():
return render(request, 'idealist/index.html')
else:
context = RequestContext(request)
activate(get_localzone())
user = UserProfile.objects.filter(user=request.user)[0]
user_projects = user.projects()
events = user.events()
event_dict = SortedDict()
string = get_localzone()
for event in reversed(events):
date = event.datew.astimezone(get_localzone())
date = date.strftime("%B") + " " + str(date.day)
if date in event_dict.keys():
event_dict[date].append(event)
else:
event_dict[date] = [event]
return render_to_response('idealist/account_home.html', {'string': string, 'user': user, 'event_dict': event_dict, 'user_projects': user_projects}, context)
Also, here are the other time-related packages that I'm importing:
from django.utils.timezone import *
import pytz
from tzlocal import *
import datetime
from pytz import timezone
Thank you so much for your help. If there is any other information I can provide you with, please let me know!
Before the answer a piece of advice, never store localized timezones. Always store dates in UTC and convert on the application as needed.
get_localzone() is probably picking up the server timezone, yours is in whatever you call local timezone while heroku server is probably set to UTC. You have a few options:
1) Set your server timezone to whatever you want
I'm not 100% sure this will work but maybe it's worth trying. Maybe setting the TZ variable to your desirable timezone will make that the local timezone. Try using:
heroku config:add TZ="America/Los_Angeles"
Replacing with your desired timezone from this list.
2) Force django to use the timezone that you want
This might be a better option since you won't have to remember to set the timezone again in case you change providers or change the heroku server.
Instead of using get_localzone() pass in the name of the timezone you want directly like this:
timezone.activate(pytz.timezone('America/Los_Angeles'))
I'm assuming you always want to use the same timezone throughout your application, but if you want to allow the user to select it's own timezone you can store that value in the user session or profile. The Django docs has some good resources on this.
Is there an easy way to be able to send an email at a later time, say Aug 1, 2012 6 pm? I have tried to read some documentation on django-mailer, but I could not get to an answer.
I am starting out in web development so may not be able to hack the existing application of django-mailer to get this done.
Celery can fit your need.
First set up a celery task:
#task
def sendmail():
pass
Send a mail later, an example from the doc:
from datetime import datetime, timedelta
tomorrow = datetime.now() + timedelta(days=1)
sendmail.apply_async(args=[], eta=tomorrow)
I'm trying to build a blurb of text that I'll ultimately send in an SMS message. The blurb includes text of a datetime object that has UTC as the timezone, but needs the text to be localized for the user's timezone instead. I have the user's timezone stored in the db.
I know that I can use timezone.activate() and timezone.deactivate() to change the current timezone, but I don't know if that's the best thing to do, when all I want is the text of the datetime to print out in the user's local timezone. I don't know if changing the current timezone will have unwanted system consequences, even if just for a short time.
Activating timezone using timezone.activate() will only affect current request, so there is really no "unwanted system consequences" to worry about.
By activating the timezone in middleware:
from django.utils import timezone
class TimezoneMiddleware(object):
def process_request(self, request):
if request.user.is_authenticated():
timezone.activate(request.user.get_profile().timezone)
you'll be able to render user's local time by using {{ datatime }} parameter in your SMS template.