Mensagens para os usuários no Django
Ultimamente tenho usado muito a aplicação de autenticação do Django. Mas não estava muito satisfeito com o sistema de mensagens para os usuários que é oferecido. Na verdade a intenção é ser realmente bem simples, vejamos um exemplo:
def alterar_foto(request):
# executa o código da view aqui....
request.user.message_set.create(message=u'Foto alterada')
return render_to_response('usuarios/dados.html',
context_instance=RequestContext(request))
Foi adicionado uma mensagem para o usuário, assim podemos criar uma fila das últimas ações executadas pelo mesmo. Só que o método para acessar essas mensagens é o get_and_delete_messages():
mensagens = user.get_and_delete_messages()
e no template, assumido que esteja usando RequestContext, ficaria assim:
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
pois o RequestContext define no template a variável messages, que são as mensagens do usuário logado. Mas como o próprio nome do método já diz, quando as mensagen são acessadas, elas são removidas. Eu não gostei muito disso, pelo fato de o usuário só poder ver as últimas ações uma única vez, além de que não tem um campo de data no model Message, pra mostrar o dia e hora daquela ação.
Daí decidi reinventar a roda, e fazer um sisteminha de mensagens com essas características. Eu fiz as mensagens acopladas a um perfil que eu criei pra o usuário do django, e não vou detalhar como se criar um perfil para seu User, veja mais aqui(lá no final do capítulo) e aqui.
Bem, basicamente é esse model:
class Action(models.Model):
user = models.ForeignKey(UserProfile)
action = models.CharField(max_length=200)
pub_date = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.action
class Meta:
ordering = ('-pub_date',)
db_table = 'auth_user_profile_action'
Onde a classe UserProfile
, é minha classe que extende o User da aplicação contrib.auth do Django.
Daí eu adicionei um método na classe UserProfile
:
from django.contrib.auth.models import User
class UserProfile(models.Model):
# meus campos extras
user = models.ForeignKey(User, unique=True)
# mais alguns método aqui, como o __unicode__, a class Meta, class Admin, etc
def keep_actions(self, maximum=10):
actions = self.action_set.count()
if actions > maximum:
extras = self.action_set.all()[maximum:actions]
for extra in extras:
extra.delete()
A intenção é a seguinte: sempre ter um número máximo de ‘ultimas ações’ do usuário, então esse método keep_settings()
recebe um parâmatro opcional(valor default é 10), que vai ser o número máximo de ações que ele vai permitir na tabela. É mais um método pra “limpar” as ações antigas.
Um exemplo de uso:
def adicionar_foto(request):
# codigo normal da view...
profile = request.user.get_profile()
profile.action_set.create(action=u'Foto adicionada')
profile.keep_actions()
profile.save()
# termina a view normalmente....
Aí eu adiciono uma ação relacionada com meu usuário, e o método keep_settings()
vai garantir que terá no máximo 10 “ultimas ações”, caso tenha mais de 10, ele remove as mais antigas e deixa apenas as 10 mais recentes.
E no template ficaria assim:
<ul>
{% for action in request.user.get_profile.action_set.all %}
<li>{{ action.pub_date|date:'d/m/Y H:i' }} - {{ action }}</li>
{% endfor %}
</ul>
Assim eu mostro a hora que a ação foi executada e deixo sempre um histórico de 10 ou mais últimas ações. Pra deletar todas poderia chamar o método keep_actions(0)
passando zero como parâmetro.