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.
- Create a new project. You can check the steps here
rails new viewproject
- 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.
- 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:
- 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 %>
- 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:
- 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.
- 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
- 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
- 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 %>