In this post, we will understand how to use layouts, views and partial views in Django.

Convention over Configuration

By default Rails follows conventions. This means, if there is a method named show in controller test_controller, Rails assumes that the view file for show action should be found in path:

app\views\test\show.html.erb

Let us understand rendering in Rails with an example.

  1. Create a new project. You can check the steps here
     rails new viewproject
  2. Now, create a new controller:
     rails generate controller test index

    This command will create following files:

    app\controllers\test_controller.rb
    app\views\test\index.html.erb

    So, for the action index in the controller test_controller, rails created index.html.erb inside the views\test folder.

  3. Start the server and run the URL:
    rails server

    Browse to the URL:

    http://localhost:3000/test/index
Rendering a different view

It is not necessary to render (display) a view with the same name as name of action. We will render a view different name in the following example:

Let us add a new method named hello in the controller test_controller:

def hello
   render 'abc'
end

Create a new view file:

app\views\test\abc.html.erb

Add the following entry in config\routes.rb:

get 'test/hello'

Now, browse to the URL:

http://localhost:3000/test/hello

This time, rails will render the view abc.html.erb instead of hello.html.erb

Rendering a view from different controller

In the following example, we will render a view that belongs to a different controller’s action.

First we will create a new controller named data with an action show:

rails generate controller data show

Now, edit the method show:

def show
   render 'test/index'
end

Now, browse to the URL:

http://localhost:3000/data/show

This time, rails will render the view test\index.html.erb instead of data\show.html.erb

Render data instead of view

We can avoid a view altogether and put simple text message for an action. Here is an example:

def show
   render plain: "This is a simple message"
end

We can render HTML like this:

def show
   render html: "<b>Not found</b>".html_safe
end

We can render JSON like this:

def show
    render json: {"name" => "ashutosh pandey", "country" => "India"}
end

We can also render Ruby code like this:

def show
    render inline:  "<% (1..10).each do |x| %> " \
                    "<%= x*x %><br/>" \
                    "<% end %>"
end
Force downloading a file

We can send a file to the browser as download.

Let us put an image named profile.jpg in our public folder of the application. Now, in your action, add following line:

def show
    send_file Rails.root.join("public", 'profile.jpg'), :type => 'image/jpeg', :disposition => 'attachment'
end
Returning status instead of any data

We can return HTTP status instead of view or any other data. We can write a statement like this:

render status :500
Rendering partial views

Partial views are reusable UI components that can be used in multiple views. For example, you want to create a calendar and want to display it on multiple pages. For this, you create a partial view and put the calendar logic there. Now include this partial view on multiple pages.

Partial views generally start with underscore. For example: _loginform.html.erb

Let us create a partial view example. Create a new folder named partials (or any other name) inside app\views folder:

app\views\partials

Now create a file named _today.html.erb inside the partials folder. Add following code to this file:

<%= Date.today.strftime("%B-%d-%Y") %>

Now, create a new controller with an action:

rails generate controller data index

This command will create following files:

app\controllers\data_controller
app\views\data\index.html.erb

Add following line to index.html.erb

<%= render partial: 'partials/today' %>

Now start your server and visit the URL:

http://localhost:3000/data/index
Rendering partial views with passing data

While rendering a partial view, we can also pass data to it. Here is an example:

  1. Create a new partial view named _table.html.erb in app\views\partials folder. We will print table of a number in the partial view by passing a number to it. Add following code to the file:
    <% (1..10).each do |i| %>
        <%=number%> x <%=i%> = <%=number*i%> <br/>
    <% end %>
  2. Now, to render this view, we can use:
    <%= render partial: 'partials/table', :locals => {:number => 5} %>

    Here, we are passing the variable number whose value is 5 to the partial view.

Layouts

Layout is a view component that is used to provide common looks to multiple pages in the application. A layout file contains html common to multiple pages. It contains sections where we can insert views for corresponding actions.

Let us understand layouts with an example:

  1. Create a new file named mylayout.html.erb in the app\views\layouts folder. Add following code to this file:
    <!DOCTYPE html>
    <html>
    <head>
      <title>Myapp</title>
      <%= csrf_meta_tags %>
    </head>
    <body>
    
    <h1>Here you can create header in layout</h1>
    
    <%= yield %>
    
    <h1>Here you can create footer in layout</h1>
    
    </body>
    </html>

    The <%= yield %> statement will include the view associated for the called action.

  2. Now, let us create a new controller named static with two actions about and contact:
     rails generate controller static about contact

    This command will create following files:

    app\controllers\static_controller.rb
    app\views\static\about.html.erb
    app\views\static\contact.html.erb
  3. Now, we need to add the following line in app\controllers\static_controller.erb file:
    layout 'mylayout'

    So, our controller class looks like this:

    class StaticController < ApplicationController
    
      layout 'mylayout'           # we will use this layout for all methods in our controller
    
      def about
      end
    
      def contact
      end
    end
  4. Start your server and visit the URLs:
    http://localhost:3000/static/about

    and

    http://localhost:3000/static/contact

    In both the cases, you will see the header and footer present in the views. Hence, we don’t have to create our headers and footers on all the view pages which definitely saves our time.

*Note: If you want to restrict your layout to only specific actions, you can do this with the statement:

layout 'mylayout', only: [:about]

content_for

We can create named sections in layouts and pass content for it when page is rendered. Here is an example layout file:

<!DOCTYPE html>
<html>
<head>
  <title>Myapp</title>
  <%= csrf_meta_tags %>
  <%= yield :js_top %>
</head>
<body>

<h1>Here you can create header in layout</h1>

<%= yield %>

<h1>Here you can create footer in layout</h1>

<%= yield :js_bottom %>

</body>
</html>

Now in our view, we can use it like this:

<% content_for :js_top do %>
    <script type="text/javascript">//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js</script>
<% end %>

<% content_for :js_bottom do %> 
    <script src="//code.jquery.com/jquery-1.11.3.min.js"></script> 
<% end %>