Como utilizar sessões¶
O Django provê suporte integral para sessões anônimas. O framework de sessão deixa você armazenar e recuperar dados arbitrários para cada visitante do site. Ele armazena dados no lado do servidor e abstrai o envio e recebimento de cookies. Os cookies contêm um ID da sessão – não os dados em si.
Habilitando as sessões¶
As sessões são implementadas por meio de um middleware.
Para habilitar a funcionalidade de sessões, faça o seguinte:
Edite o parâmetro de configuração
MIDDLEWARE_CLASSES
e assegure-se de que ele contenha'django.contrib.sessions.middleware.SessionMiddleware'
. O arquivo padrãosettings.py
criado pelodjango-admin.py startproject
tem oSessionMiddleware
ativado.Adicione
'django.contrib.sessions'
à sua configuraçãoINSTALLED_APPS
e rodemanage.py syncdb
para instalar a única tabela de banco de dados que armazena os dados de sessão.Novo na versão de desenvolvimento do Django: esse passo é opcional se você não estiver usando um backend de sessão de banco de dados; veja configurando o mecanismo de sessão.
Se você não deseja utilizar sessões, você pode remover a linha
SessionMiddleware
do MIDDLEWARE_CLASSES
e 'django.contrib.sessions'
de seu INSTALLED_APPS
. Isso poupará um pouco o processamento adicional.
Configurando o mecanismo de sessão¶
Por padrão, o Django armazena as sessões no seu banco de dados (usando o modelo
django.contrib.sessions.models.Session
). Apesar de ser conveniente, em
algumas configurações é mais rápido armazenar esses dados em algum outro lugar,
então o Django pode ser configurado para armazenar dados de sessão no seu
sistema de arquivos ou no cache.
Usando sessões baseadas em arquivos¶
Para usar sessões em arquivos, configure o parâmetro SESSION_ENGINE
para
"django.contrib.sessions.backends.file"
.
Você pode querer configurar o parâmetro SESSION_FILE_PATH
(que obtém o
valor padrão de saída de tempfile.gettempdir()
, comumente /tmp
) para
controlar onde o Django deve armazenar os arquivos de sessão. Certifique-se de
que seu servidor Web tem permissão para ler e escrever neste local.
Usando sessões baseadas em cache¶
Para armazenar dados de sessão utilizando o sistema de cache do Django,
configure SESSION_ENGINE
para "django.contrib.sessions.backends.cache"
.
É importante confirmar que o seu cache esteja configurado; veja a
documentação de cache para mais detalhes.
Note
Você provavelmente só deve utilizar sessões baseadas em cache se estiver usando o backend de cache Memcached. O backend de cache de memória local não guarda os dados por um período longo o suficiente para ser considerado uma boa escolha, e será mais rápido usar sessões de arquivos ou banco de dados diretamente em vez de enviar tudo por meio do backend de cache baseado em arquivos ou banco de dados.
Utilizando sessões nas views¶
Quando SessionMiddleware
está ativo, cada objeto HttpRequest
– o
primeiro argumento para qualquer view em Django – terá um atributo
session
, que é um objeto que se comporta como dicionário. Você pode ler ou
escrever nele.
Ele implementa os seguintes métodos padrões de dicionários:
__getitem__(key)
Exemplo:
fav_color = request.session['fav_color']
__setitem__(key, value)
Exemplo:
request.session['fav_color'] = 'blue'
__delitem__(key)
Exemplo:
del request.session['fav_color']
. Se a chavekey
ainda não está na sessão, uma exceçãoKeyError
será lançada.__contains__(key)
Exemplo:
'fav_color' in request.session
get(key, default=None)
Exemplo:
fav_color = request.session.get('fav_color', 'red')
keys()
items()
setdefault()
clear()
setdefault()
and clear()
são novos nesta versão.Existem também estes métodos:
flush()
Deleta os dados da sessão corrente da sessão, e re-gera a chave o valor da chave da sessão que é enviado de volta para o cookie do usuário. Isto é usado se você quer assegurar que os dados de uma sessão prévia não possa ser acessados novamente por usuário do navegador (por exempo, a função :func:
django.contrib.auth.logout()
o chama).set_test_cookie()
Cria um cookie de teste para determinar se o navegador do usuário suporta cookies. Devido à maneira como os cookies funcionam, você não é capaz de testá-lo até que o usuário requisite a próxima página. Veja Criando cookies de teste abaixo para mais informações.
test_cookie_worked()
Devolve
True
ouFalse
, a depender de o navegador do usuário ter aceito o cookie de teste ou não. Devido à maneira como os cookies funcionam, você deverá chamarset_test_cookie()
em uma requisição anterior de uma página separada. Veja Criando cookies de teste abaixo para mais informações.delete_test_cookie()
Apaga o cookie de test. Use isto você mesmo, para limpar tudo.
set_expiry(value)
Configura o tempo de expiração para a sessão. Você pode passar vários valores diferentes:
- Se
value
é um inteiro, a sessão irá expirar depois dessa quantidade de segundos de inatividade. Por exemplo, chamarrequest.session.set_expiry(300)
fará com que a sessão expire em 5 minutos. - Se
value
é um objetodatetime
outimedelta
, a sessão irá expirar nessa data/hora específica. - Se
value
é0
, o cookie de sessão do usuário expirará quando o navegador Web do usuário for fechado. - Se
value
éNone
, a sessão volta a utilizar a política global de expiração.
- Se
get_expiry_age()
Devolve o número de segundos até que a sessão expire. Para sessões sem uma expiração customizada (ou aquelas que são configuradas para expirar quando o navegador fecha), esse valor será igual a
settings.SESSION_COOKIE_AGE
.get_expiry_date()
Devolve a data em que a sessão expirará. Para sessões sem expiração customizada (ou aquelas que são configuradas para expirar quando o navegador fechar), esse valor é igual à data
settings.SESSION_COOKIE_AGE
segundos de agora.get_expire_at_browser_close()
Devolve
True
ouFalse
, dependendo se o cookie de sessão do usuário expirar quando o navegador Web do usuário for fechado.
Você pode editar request.session
em qualquer ponto de sua view, podendo
ser editado múltiplas vezes.
Guia de uso do objeto de sessão¶
- Use strings normais Python como chaves de dicionário em
request.session
. Isso é mais uma convenção do que uma regra. - Chaves de dicionário de sessão que começam com “underscore” (“_”) são reservadas para uso interno do Django.
- Nâo sobrescreva
request.session
com um novo objeto e não acesse ou mude o valor de seus atributos. Use-o como um dicionário Python.
Exemplos¶
Esta view simplista muda o valor da variável has_commented
para True
depois que um usuário posta um comentário. Ela não deixa que um usuário
poste um comentário mais de uma vez:
def post_comment(request, new_comment):
if request.session.get('has_commented', False):
return HttpResponse(u"Você já comentou.")
c = comments.Comment(comment=new_comment)
c.save()
request.session['has_commented'] = True
return HttpResponse(u'Obrigado pelo seu comentário!')
Esta outra view simples autentica um “membro” do site:
def login(request):
m = Member.objects.get(username=request.POST['username'])
if m.password == request.POST['password']:
request.session['member_id'] = m.id
return HttpResponse(u"Você está autenticado.")
else:
return HttpResponse(u"Seu nome de usuário e senha não conferem.")
...E esta encerra a sessão do membro, de acordo com o login()
acima:
def logout(request):
try:
del request.session['member_id']
except KeyError:
pass
return HttpResponse(u"Você saiu.")
A função padrão django.contrib.auth.logout()
na verdade faz um pouco mais do
que isso para evitar fugas de dados inadvertida. Ele chama
request.session.flush()
. Nós estamos usando este exemplo como uma
demonstração de como trabalhar com objetos de sessão, não uma implementação
completa de logout()
.
Criando cookies de teste¶
Como uma conveniência, o Django provê uma maneira fácil de testar se o navegador
do usuário aceita cookies. Simplesmente chame
request.session.set_test_cookie()
em uma view e chame
request.session.test_cookie_worked()
em uma view subseqüente – não na
mesma chamada de view.
Essa estranha separação entre set_test_cookie()
e test_cookie_worked()
é necessária devido à maneira como os cookies funcionam. Quando você cria um
cookie, você não pode dizer se o navegador o aceitou até a próxima requisição do
navegador.
É uma boa prática usar delete_test_cookie()
para limpar o cookie de teste.
Faça isso depois que você verificou que o cookie funcionou.
Aqui vai um exemplo típico de uso:
def login(request):
if request.method == 'POST':
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponse(u"Você está autenticado.")
else:
return HttpResponse(u"Por favor habilite os cookies e tente novamente.")
request.session.set_test_cookie()
return render_to_response('foo/login_form.html')
Usando sessões fora das views¶
Uma API está disponível para manipular os dados da sessão fora de uma view:
>>> from django.contrib.sessions.backends.db import SessionStore
>>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
>>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10)
>>> s['last_login']
datetime.datetime(2005, 8, 20, 13, 35, 0)
>>> s.save()
Se você está usando o backend django.contrib.sessions.backends.db
, cada
sessão é simplesmente um modelo normal do Django. O modelo Session
é
definido em django/contrib/sessions/models.py
. Por ser um modelo normal,
você pode acessar as sessões usando a API normal de banco de dados do Django:
>>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)
Note que você precisa chamar get_decoded()
para obter o dicionário da
sessão. Isso é necessário porque o dicionário é armazenado em um formato
codificado:
>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>> s.get_decoded()
{'user_id': 42}
Quando as sessões são gravadas¶
Por padrão, o Django somente grava no banco de dados da sessão quando ela foi modificada – ou seja, se algum de seus valores de dicionário foram atribuídos ou apagados:
# A sessão é modificada.
request.session['foo'] = 'bar'
# A sessão é modificada.
del request.session['foo']
# A sessão é modificada.
request.session['foo'] = {}
# Pegadinha: A sessão NÃO é modificada, porque isso altera
# request.session['foo'] em vez de request.session.
request.session['foo']['bar'] = 'baz'
No último caso do exemplo acima, podemos dizer explicitamente ao objeto de
sessão que ele foi modificado por meio do atributo modified
do objeto
de sessão:
request.session.modified = True
Para mudar esse comportamento padrão, coloque o valor de configuração
SESSION_SAVE_EVERY_REQUEST
para True
. Se SESSION_SAVE_EVERY_REQUEST
for True
, o Django gravará a sessão no banco de dados a cada requisição.
Note que o cookie de sessão somente é enviado quando uma sessão foi criada ou
modificada. Se SESSION_SAVE_EVERY_REQUEST
for True
, o cookie de sessão
será enviado em todos os requests.
Similarmente, a parte de expires
de um cookie de sessão é atualizado a cada
vez que o cookie é enviado.
Limpando a tabela de sessão¶
Se você está usando um banco de dados como backend para as sessões, perceba que os dados de sessão podem acumular
na tabela de banco de dados django_session
e o Django não dispõe de uma limpeza automática. Portanto,
é seu trabalho limpar as sessões expiradas regularmente.
Para entender esse problema, considere o que acontece quando um usuário usa uma
sessão. Quando um usuário se autentica, o Django adiciona uma linha na tabela
django_session
. O Django atualiza essa linha cada vez que os dados da
sessão mudam. Se o usuário encerra sua sessão manualmente (logout), o Django
apaga essa linha. Mas se o usuário não sai (não dá logout), a linha nunca é
apagada.
O Django tem um script de exemplo para limpeza em django-admin.py cleanup
.
Esse script apaga qualquer sessão na tabela em que expire_date
está em
uma data no passado –, mas sua aplicação pode ter requisitos diferentes.
Configurações¶
Algumas configurações do Django te dão controle sobre o comportamento de sessões:
SESSION_ENGINE¶
Padrão: django.contrib.sessions.backends.db
Controla onde o Django armazena os dados de sessão. Os valores válidos são:
'django.contrib.sessions.backends.db'
'django.contrib.sessions.backends.file'
'django.contrib.sessions.backends.cache'
Veja configurando o mecanismo de sessão para mais detalhes.
SESSION_FILE_PATH¶
Padrão: /tmp/
Se você está usando um armazenamento baseado em arquivos, esse parâmetro configura o diretório no qual o Django irá armazenar os dados de sessão.
SESSION_COOKIE_AGE¶
Padrão: 1209600
(2 semanas, em segundos)
O tempo de duração de um cookie de sessão, em segundos.
SESSION_COOKIE_DOMAIN¶
Padrão: None
O domínio para seu usado nos cookies de sessão. Configure-o para uma string
como ".lawrence.com"
(repare no ponto inicial) para cookies entre domínios diferentes (cross-domain
cookies), ou use None
para um cookie de domínio padrão.
SESSION_COOKIE_NAME¶
Padrão: 'sessionid'
O nome do cookie a usar para as sessões. Esse valor pode ser o que você quiser.
SESSION_COOKIE_SECURE¶
Padrão: False
Se deseja usar cookie seguro para os cookies de sessão ou não. Se este
parâmetro for True
, o cookie será marcado como “seguro”, o que significa
que os navegadores devem assegurar-se de que o cookie somente será enviado por
meio de uma conexão HTTPS.
SESSION_EXPIRE_AT_BROWSER_CLOSE¶
Padrão: False
Se a sessão deve expirar quando o usuário fecha seu navegador. Veja “Sessões que duram até o navegador fechar contra sessões persistentes” acima.
SESSION_SAVE_EVERY_REQUEST¶
Padrão: False
Se os dados da sessão devem ser gravados a cada request. Se for False
(padrão), então os dados da sessão somente serão gravados quando forem
modificados – ou seja, se algum dos valores de seu dicionário forem alterados
ou excluídos.
Detalhes técnicos¶
- O dicionário de sessão deve aceitar qualquer objeto Python que possa ser serializado com “pickle”. Veja o módulo pickle para mais informações.
- Os dados de sessão são armazenados em uma tabela de banco de dados
chamada
django_session
. - O Django somente envia o cookie se for necessário. Se você não coloca nenhum dado na sessão, ele não enviará o cookie de sessão.
IDs de sessão em URLs¶
O framework de sessão do Django é única e inteiramente baseado em cookies. Ele não tenta colocar IDs de sessão em URLs como um último recurso se o navegador não aceita cookies, como o PHP faz. Isso é uma decisão de projeto intencional. Esse comportamento não só cria URLs horríveis, como deixa seu site vulnerável a roubo de ID de sessão por meio do cabeçalho “Referer”.