Wednesday, February 14, 2007

Moving from Rails to Django: Replacing flash[:notice]

One of the most common practices I came across while learning Rails is the flash[:notice] mechanism used to send (error) messages to the template. Consequently it was also one of my first targets to migrate when I started moving a pet application from Rails to Django.

I came up with a simple (and all too obvious) way to send error messages to the template. I am sure that there are better ways to do this. If you know of any, please take a minute to share them.

First, the Rails snippet.
  1. def index  
  2.  ...  
  3.  begin          
  4.   army = Army.find(params[:army][:id])          
  5.  rescue StandardError => se          
  6.   flash[:notice] = "Vare, legiones redde!"          
  7.   return      
  8.  end      
  9.  ...  
  10. end  
Next, the equivalent in Django.
  1. from django.shortcuts import render_to_response  
  2.   
  3. def index(request):  
  4.     ...  
  5.     try:  
  6.         army = Army.objects.get(id = request.POST["army"])  
  7.   
  8.     except ( KeyError, Army.DoesNotExist ):  
  9.         return render_to_response( "some_template.html", { "flash" : "Vare, legiones redde!" } )  
  10.     ...  
The template in Rails ...
  1. ...  
  2. <% if @flash[:notice] -%>  
  3. <div id="flash">  
  4.         <div><%= @flash[:notice] %></div>  
  5. </div>  
  6. <% end -%>  
  7. ...  
... and the template in Django.
  1. ...  
  2. {% if flash %}  
  3. <div id="flash">  
  4.         <div>{{ flash }}</div>  
  5. </div>  
  6. {% endif %}  
  7. ...  
While testing in Django, flash can be treated just like any other context variable.

4 comments:

Ian said...

Unfortunately, flash in Rails works not only for forwards to the template, but also across a 302 redirect.

Anonymous said...

You are probably much happier with
request.user.message_set.create(message='Your Message goes here')

Manoj Govindan said...

Thanks. I will remember to use user.message_set in the future.

x said...

There is a better way.
You can place you messages in session.
For example, request.session['message']
Then in templates just get it from request.session.message
You'll have to use middleware which will empty request.session['message'] in the beginning of all requests.
If you want to set message for the next page after redirect then you can use request.session['next_message'] and special middleware which will convert 'next_mesage' to 'message' in the beginning of all requests.