views:

656

answers:

3

I often show messages about user actions to logged in users in my Django app views using:

request.user.message_set.create("message to user")

How could I do the same for anonymous (not logged in) users? There is no request.user for anonymous users, but the Django documentation says that using the "session" middleware you can do the same thing as the above code. The Django documentation that links to the session middleware claims it is possible, but I couldn't find how to do it from the session documentation.

+4  A: 

Store the data directly in the session, which is a dict-like object. Then in the view/template, check for the value.

More information here:

http://docs.djangoproject.com/en/dev/topics/http/sessions/#using-sessions-in-views

You could also create a middleware class to check for the session object on each request, and do your build up/tear down there.

Daniel
+5  A: 

This is what I do, using context processors:

project/application/context.py (check for messages and add them to the context):

def messages(request):
    messages = {}
    if 'message' in request.session:
        message_type = request.session.get('message_type', 'error')
        messages = {'message': request.session['message'],
                    'message_type': message_type}
        del request.session['message']
        if 'message_type' in request.session:
            del request.session['message_type']
    return messages

project/settings.py (add the context to the TEMPLATE_CONTEXT_PROCESSORS):

TEMPLATE_CONTEXT_PROCESSORS = (
    "django.core.context_processors.request",
    "django.core.context_processors.debug",
    "django.core.context_processors.media",
    "django.core.context_processors.auth",
    "project.application.context.messages",  
)

With the above the function messages will be called on every request and whatever it returns will be added to the template's context. With this in place, if I want to give a user a message, I can do this:

def my_view(request):
    if someCondition:
        request.session['message'] = 'Some Error Message'

Finally, in a template you can just check if there are errors to display:

{% if message %}
    <div id="system_message" class="{{ message_type }}">
        {{ message }}
    </div>
{% endif %}

The message type is just used to style depending on what it is ("error","notice","success") and the way that this is setup you can only add 1 message at a time for a user, but that is all I really ever need so it works for me. It could be easily changed to allow for multiple messages and such.

Paolo Bergantino
+4  A: 

See http://code.google.com/p/django-session-messages/ until the patch that enables session based messages lands in Django tree (as I saw recently, it's marked for 1.2, so no hope for quick addition...).

Another project with similar functionality is Django Flash (http://djangoflash.destaquenet.com/).

zgoda
unfortunately django_session_messages won't work with the django.core.context_processors.auth which deletes all user messages before code in this patch will run. Probably one might consider re-doing the whole message system in django.
Evgeny
if you flip order of the two context processors in the settings, the second one will overwrite the message list, so it won't help either.
Evgeny