13. Making Rango Tango! Exercises¶
So far we have been adding in different pieces of functionality to Rango. We’ve been building up the application in this manner to get you familiar with the Django Framework, and to learn about how to construct the various parts of a website that you are likely to make in your own projects. Rango however at the present moment is not very cohesive. In this chapter, we challenge you to improve the application and its user experience by bringing together functionality that we’ve already implemented alongside some awesome new additions.
To make Rango more coherent and integrated it would be nice to add the following functionality.
- Integrate the browsing and searching within categories, i.e.:
- Provide services for Registered Users, i.e.:
- let users view their profile;
- let users edit their profile; and
- let users see the list of users and their profiles.
- Track the click throughs of Categories and Pages, i.e.:
- count the number of times a category is viewed;
- count the number of times a page is viewed via Rango; and
- collect likes for categories (see Chapter 15).
Note
We won’t be working through all of these tasks right now. Some will be taken care of in Chapter 15, while some will be left to you to complete as additional exercises.
Before we start to add this additional functionality we will make a todo list to plan our workflow for each task. Breaking tasks down into sub-tasks will greatly simplify the implementation and mean that we are attacking each one with a clear plan. In this chapter, we will provide you with the workflow for a number of the above tasks. From what you have learnt so far, you should be able to fill in the gaps and implement most of it on your own. The following chapter however includes the code walkthrough, along with notes on how we have implemented each task.
13.1. Providing Categories on Every Page¶
It would be nice to show the different categories that users can browse through on any page, and not just the index page. There are a number of ways that this can be achieved, but given what we have learnt so far, we could undertake the following workflow:
Create a
category_list.html
template and migrate the template code for presenting the categories list fromindex.html
to this new template. This template won’t be a full HTML document, but a portion of one which we can include in other templates.- Use the
{% include "rango/category_list.html" %}
to now include this template code into thebase.html
template within the sidebar. This means that all pages will now include categories, assuming thecat_list
data is passed through in the context dictionary. - To handle the scenario where
cat_list
isn’t available, add the conditional{% if cat_list %}
to ensure that only templates providingcat_list
attempt to render this component.
- To handle the scenario where
- Use the
- Migrate the code that gathers the list of categories from the
index()
view and place it into yourcategory()
view. While it’s really tempting to simply copy and paste, there’s a much better way to go about this! - Create a helper function called
get_category_list()
withinviews.py
that returns the list of categories. - We can then call this function whenever we want to get the category list to be presented in the sidebar. This saves a lot of code repetition!
- Create a helper function called
- Migrate the code that gathers the list of categories from the
Pass the category list data (
cat_list
) through to the template to complete the process.
13.2. Searching Within a Category Page¶
Rango aims to provide users with a helpful directory of page links. At the moment, the search functionality is essentially independent of the categories. It would be nicer however to have search integrated into category browsing. Let’s assume that a user will first browse their category of interest first. If they can’t find the page that they want, they can then search for it. If they find a page that is suitable, then they can add it to the category that they are in. Let’s tackle the first part of this description here.
We first need to remove the global search functionality and only let users search within a category. This will mean that we essentially decommission the current search page and search view. After this, we’ll need to perform the following steps.
- Remove the generic Search link from the menu bar.
- Take the search form and results template markup from
search.html
and place it intocategory.html
. - Update the category view to handle a HTTP
POST
request. The view must then include any search results in the context dictionary for the template to render.
13.3. View Profile¶
Another useful feature to add is a profile page, where users can view details of their Rango profile. Undertake the following steps to add this functionality.
- First, create a template called
profile.html
. In this template, add in the fields associated with the user profile and the user (i.e. username, email, website and picture). - Create a view called
profile()
. This view will obtain the data required to render the user profile template. - Map the URL
/rango/profile/
to your newprofile()
view. - In the base template add a link called Profile into the menu bar, preferably on the right-hand side with other user-related links. This should only be available to users who are logged in (i.e.
{% if user.is_authenticated %}
).
13.4. Track Page Click Throughs¶
Currently, Rango provides a direct link to external pages. This is not very good if you want to track the number of times each page is clicked and viewed. To count the number of times a page is viewed via Rango you will need to perform the following steps.
Create a new view called
track_url()
, and map it to URL/rango/goto/
.- The
track_url()
view will examine the HTTPGET
request parameters and pull out thepage_id
. The HTTPGET
requests will look something like/rango/goto/?page_id=1
. - Your view should then be able to find the relevant
Page
model for the selected page, and add 1 to the associatedviews
field. - The view will then redirect the user to the specified URL using Django’s
redirect
method. - In the scenario where no parameters are in the HTTP
GET
request forpage_id
, or the parameters do not return aPage
object, redirect the user to Rango’s homepage.
- Your view should then be able to find the relevant
- The
Update the
category.html
so that it uses/rango/goto/?page_id=XXX
instead of using the direct URL.
13.4.1. Hint¶
If you’re unsure of how to retrieve the page_id
querystring from the HTTP GET
request, the following code sample should help you.
if request.method == 'GET':
if 'page_id' in request.GET:
page_id = request.GET['page_id']
Always check the request method is of type GET
first, then you can access the dictionary request.GET
which contains values passed as part of the request. If page_id
exists within the dictionary, you can pull the required value out with request.GET['page_id']
.