Sessões
Sessões são um mecanismo usado em aplicações web para armazenar informações específicas do usuário entre diferentes requisições. Em essência, uma sessão permite que um servidor saiba quem está interagindo com ele, mantendo dados de estado sobre um usuário específico. Ela persiste mesmo que o navegador seja fechado e o computador desligado, onde a decisão de encerramento de sessão parte do programado. Os dados de uma sessão dura enquanto a sessão estiver ativa ou seja limpa.
Quando um usuário acessa um site, o servidor cria uma identidade única para ele (um "session ID"). Essa identidade é armazenada no navegador do usuário, geralmente como um cookie. O servidor associa o "session ID" a um conjunto de dados (chamado de "dados de sessão"). Esses dados podem incluir informações como autenticação do usuário, preferências (idioma, tema, etc.), itens em um carrinho de compras e etc.

Por padrão, o cookie chamado sessionid é enviado ao navegador do cliente. Esse cookie não contém os dados da sessão, mas apenas um identificador único que mapeia para os dados reais da sessão no backend.
Os dados reais da sessão (como avaliacao_favorita) são armazenados no local configurado em SESSION_ENGINE do Django. As opções mais comuns são: Banco de Dados: (Padrão: django.contrib.sessions.backends.db) onde os dados da sessão são salvos em uma tabela chamada django_session no banco de dados. Cache: (django.contrib.sessions.backends.cache) que armazena os dados em um cache, como Redis ou Memcached. Arquivo no Servidor: (django.contrib.sessions.backends.file) que salva os dados em arquivos locais no servidor. resumindo o Django por padrão consulta a tabela django_session usando o sessionid.
INSTALLED_APPS = [
'django.contrib.sessions',
]
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
]
# Define a duração dos cookies
SESSION_COOKIE_AGE = 120
Essas linhas devem ser verificadas para que as sessões funcionem no Django, e adicionado uma linha que definirá a duração do cookie. por padrão são duas semanas. A sua definição é feita em segundos (120 seriam 2 minutos).
| Exemplo Sessão
O exemplo da sessão gira em torno de qual avaliação é a favorita. A propriedade Django request.session, é usada para armazenar ou consultar dados da sessão.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Detalhes Avaliação</title>
</head>
<body>
<h1>{{ avaliacao.nome_usuario }}</h1>
<p>Nota: {{ avaliacao.avaliacao }}</p>
<p>{{ avaliacao.descricao }}</p>
<form action="/avaliacoes/favorita" method="POST">
{% csrf_token %}
<input type="hidden" name="avaliacao_id" value="{{ avaliacao.id }}">
<button type="submit">Favorita</button>
</form>
</body>
</html>
from django.views import View
from django.views.generic import TemplateView
from .models import Avaliacao
class AddFavoritaView(View):
def post(self, request):
avaliacao_id = request.POST['avaliacao_id']
# Adiciono uma nova chave na sessão como o id da avaliacao
request.session["avaliacao_favorita"] = avaliacao_id
return HttpResponseRedirect("/avaliacao/"+ avaliacao_id)
class AvaliacaoDetailView(TemplateView):
template_name = "meu_app/avaliacao_detalhe.html"
model = Avaliacao
O django fará automaticamente com que a avaliacao_favorita seja salva no banco de dados juntamente com outros dados de sessão.
from django.urls import path
from . import views
urlpatterns = [
path('avaliacoes/favorita/', views.AddFavoritaView.as_view()),
path("avaliacao/<int:pk>", views.AvaliacaoDetailView.as_view()),
]
from django.db import models
class Avaliacao(models.Model):
nome_usuario = models.CharField(max_length=20)
descricao = models.TextField()
avaliacao = models.IntegerField()
def __str__(self):
return self.nome_usuario
SERIALIZAÇÃO
É o processo de converter um objeto em um formato que possa ser armazenado ou transmitido, como JSON, XML, ou outros formatos simples. No caso do Django, as sessões geralmente utilizam JSON para serializar os dados.
Levando em consideração os arquivos do exemplo acima, abaixo teriamos um erro ao tentar armazenar um objeto complexo em uma Sessão. O erro indica que o objeto Avaliacao não pode ser serializado automaticamente em JSON. Isso ocorre porque o Django não sabe como transformar um objeto complexo (como uma instância de modelo) em um formato simples (mas saberia lidar com tipos primitivos: strings, inteiros, booleanos, dicionários e etc). A não ser que a serialização precise realmente ser feita manualmente e armazenada na sessão, a melhor prática seria do exemplo anterior, armazenar apenas o id, e posteriormente recuperar essas informações no banco.
# View que geraria erro
class AddFavoritaView(View):
def post(self, request):
avaliacao_id = request.POST['avaliacao_id']
# Nessa parte ocorrerá o erro, pois estamos puxando o objeto completo pelo id e tentando armazenar na sessão
avaliacao_favorita = Avaliacao.objects.get(pk=avaliacao_id)
request.session["avaliacao_favorita"] = avaliacao_favorita
return HttpResponseRedirect("/avaliacoes/"+ avaliacao_id)
| Buscar Dados na Sessão
class AvaliacaoDetailView(DetailView):
template_name = "meu_app/avaliacao_detalhe.html"
model = Avaliacao
# pego todo contexto e adiciono uma chave
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Pega o id do objeto atual
avaliacao_atual_id = self.object.id
# Pego o id da avaliação favorita
id_favorita = self.request.session.get("avaliacao_favorita")
# Adiciono a chave booleana ao contexto
context["is_favorita"] = id_favorita == str(avaliacao_atual_id)
return context
self.object contém o objeto (atual) que está sendo exibido pela view (no caso de um DetailView, é o objeto correspondente à chave primária passada na URL). avaliacao_favorita foi salva como string por isso converto o id do objeto atual para string para comparação.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Detalhes Avaliação</title>
</head>
<body>
<h1>{{ avaliacao.nome_usuario }}</h1>
<p>Nota: {{ avaliacao.avaliacao }}</p>
<p>{{ avaliacao.descricao }}</p>
{% if favorita %}
<p>Essas é minha postagem favorita</p>
{% endif %}
<form action="/noticias/avaliacoes/favorita/" method="POST">
{% csrf_token %}
<input type="hidden" name="avaliacao_id" value="{{ avaliacao.id }}">
<button type="submit">Favorita</button>
</form>
</body>
</html>