Preamble
In this exercise round, you will complete a small web service that provides
country and continent information. This information will be available via
simple HTTP API where the data can be fetched in JSON format. Users can
browse the data in a separate HTML and JavaScript based user interface.
You are given a started Django project including two incomplete
applications. In first exercise, you will define models and import initial data given to
you. Then in second exercise, you will complete the API views that handle
serving this data. And finally in third exercise, you will create
templates for humans to browse this data that will utilize components
created in first two exercises.
Note that tests are given to you to help with the
exercises. However, it is also useful to test your code in browser with
Django's development server.
1. Models
In this exercise, you need to implement models for
Continent
and Country
. An XML file
country/countrydata/fixtures/countrydata.xml*
is given that defines the contents for your database.
* The data in this exercise is licensed under a Creative Commons
Attribution License and downloaded from
GeoNames.org.
You must define appropriate models to hold the data. Then, create SQLite
database from the new models.
Finally, load the given data from the countrydata.xml
file by using
loaddata
.
Getting Started
1. Open the XML file and examine the data.
In the beginning of the XML file you should find the continents followed by the countries.
From the data you can easily deduce most of the requirements for the models, such as the names and types of the fields. Additional requirements for the models (not deducible from the data) are:
- Countries of a continent should be accessible through attribute
countries
of the Continent model.
- Names of continents should be unique (not to be confused with setting it as primary key).
- Codes of countries and continents should be unique (but not primary keys).
- Both models should be ordered by the
name
field by default.
2. Implement the models and makemigrations
and migrate
the database.
3. Finally, load the data into the database using the
loaddata
command.
If you installed Django in a virtualenv on Linux or OS X, remember to
activate the virtualenv before using manage.py
.
Things to read
If you run into problems or don't know where to start, the following resources might be helpful:
What to Submit?
In this exercise you must submit your implementation of the Continent
and Country
models in the models.py
.
Before submitting, you should test your program yourself.
We provide you with some Django tests: country/countrydata/tests.py
.
Refer to the first Django round for instructions how to run the tests.
Please note that the tests.py contains two tests classes, one for each exercise on this round. Thus, after solving this exercise, only the tests from class BasicDataTestCase
should pass.
Hint: you can run a single named test case separately.
$ python manage.py test countrydata.tests.BasicDataTestCase
The provided project has also the automatic administration interface
configured. You may take a look at your objects in the
admin interface if you
create a superuser in the shell.
$ python manage.py createsuperuser
To properly list the model objects, the
__str__
-function needs to be implemented.
Submitting Your Project to Plussa
Add, commit and push your new files and possible changes to the Git as in round 1.
Finally, just copy and paste your GitLab project's URL to Plussa. The file we will check
is exercises/07_django/country/countrydata/models.py
.
2. Views
Rendering JSON in Django Views
In this exercise you need to implement the views, continent_json
and country_json
,
that will return data for countries and continents in JSON
format with JSONP support. You should continue working with the same Django project
that you already worked with in the first exercise of this Django round. Your views will
use the Country and Continent models that you implemented.
Constructing JSON string
You need to turn the country data in the models to JSON.
One way to do it, would be to store the data in corresponding python
data structures (dicts and lists) and to use the json
module to encode it to JSON string. The json function dumps
does just this. See the Examples below for
how the data should be formatted.
Making the view render JSON instead of HTML
The HttpResponse objects that views return are not just for carrying HTML.
The body of an HTTP response may carry any text or data that is encoded in text.
But if you return something else than HTML, you should set the mimetype of the data in the HttpResponse. For JSON data this would be:
return HttpResponse(my_json_data,
content_type="application/json")
. There is also JsonResponse in Django.
If a continent or country with the given code is not found,
the view should respond with an HTTP response having the 404 status code.
About JSONP
Make sure you understand what JSONP is and why we need it
(see Things to Read below).
If the HTTP GET request for continent_json
or country_json
has the
callback
GET parameter, the JSON data must be wrapped in a JavaScript function call
and the name of the function must be the value of the callback
.
If there is no callback
parameter, the views should return normal JSON.
Examples
Example of the rendered JSON for the url
http://localhost:8000/api/eu/fi.json
:
{
"area": 337030,
"population": 5244000,
"capital": "Helsinki"
}
Example of the rendered JSON for the url
http://localhost:8000/api/eu/fi.json?callback=myCallbackFunction
(with JSONP callback):
myCallbackFunction({
"area": 337030,
"population": 5244000,
"capital": "Helsinki"
})
Example of the rendered JSON for the url
http://localhost:8000/api/eu.json?callback=myCallbackFunction
:
myCallbackFunction({
"xk": "Kosovo",
"ch": "Switzerland",
"gr": "Greece",
"va": "Vatican City",
"ee": "Estonia",
"is": "Iceland",
"al": "Albania",
"gg": "Guernsey",
"cz": "Czech Republic",
"cy": "Cyprus",
"sj": "Svalbard and Jan Mayen",
"im": "Isle of Man",
"at": "Austria",
"je": "Jersey",
"ad": "Andorra",
"ax": "\u00c5land Islands",
"ie": "Ireland",
"gi": "Gibraltar",
"dk": "Denmark",
"ru": "Russia",
"nl": "Netherlands",
"pt": "Portugal",
"no": "Norway",
"li": "Liechtenstein",
"lv": "Latvia",
"lt": "Lithuania",
"lu": "Luxembourg",
"es": "Spain",
"it": "Italy",
"ro": "Romania",
"pl": "Poland",
"be": "Belgium",
"fr": "France",
"bg": "Bulgaria",
"ba": "Bosnia and Herzegovina",
"hr": "Croatia",
"de": "Germany",
"hu": "Hungary",
"fi": "Finland",
"by": "Belarus",
"cs": "Serbia and Montenegro",
"fo": "Faroe Islands",
"me": "Montenegro",
"md": "Moldova",
"mc": "Monaco",
"rs": "Serbia",
"mk": "Macedonia",
"sk": "Slovakia",
"mt": "Malta",
"si": "Slovenia",
"sm": "San Marino",
"ua": "Ukraine",
"se": "Sweden",
"gb": "United Kingdom"
})
Things to Read
Here are some external resources to help you out with this exercise:
Submitting Your Project to Plussa
Add, commit and push your new files and possible changes to the Git as in round 1.
Finally, just copy and paste your GitLab project's URL to Plussa. The file we will check
is exercises/07_django/country/countrydata/views.py
.
3. Templates
Templates and views for normal requests
In this exercise, you need to implement templates that will display countries and their data in a table on the bottom of this page. The table should only be visible when a user has requested this view with a country code. Above the table there should be links to all continents in the database. If the user requests a page with a non existent continent code a 404 HTTP response code should be returned.
Templates and (changes to) views for Ajax updates
The base template and a piece of javascript that come with the exercise package will make interface improvements for this page : The continent names that link to the country tables of other continents are modified by the script so that instead of reloading the whole page, they trigger an Ajax request. This will only update the modified part of the page (ie. the table). The JavaScript code used is included in the given material. In this exercise you don't need to do the javascript, but to write the views that provide Ajax call the requested data .
You need to modify the view (show_continent
) on server side so that when it is requested with an Ajax request, it will only render the table template (selectui/countrytable.html
) instead of the whole page.
Checking whether a request is made via Ajax can be checked from information in the HttpRequest object using the is_ajax()-method.
The Templates
The given material contains an index.html
template in country/selectui/templates/selectui
. Do not modify this! Instead, write your part of the page to the templates countrytable.html
and continentmenu.html
that are included into the index.html
.
Template countrytable
The template countrytable should render a table with columns for Name, Capital, Population, and Area for all countries of the continent
passed to the template. If no continent is passed, it should simply render the headings of the table. Example for imaginary continent with only one country:
<table id="countryTable">
<thead>
<tr>
<th>Name</th>
<th>Capital</th>
<th>Population</th>
<th>Area</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sweden</td>
<td>Stockholm</td>
<td>9045000</td>
<td>449964 km2</td>
</tr>
</tbody>
</table>
Template continentmenu
The template should render an unordered list with list items including links to the continents passed to the template (as template variable all_continents
). Example with only one continent:
<ul id="continentMenu">
<li><a href="insert-path-to-continent-using-the-template">Scandinavia</a></li>
</ul>
Hints and Tips
- Read the code in the given material! Especially files
07_django/country/selectui/templates/selectui/index.html
and 07_django/country/selectui/static/selectui/ajax.js
.
- Read the given code in
07_django/country/selectui/views.py
for the show_continent
view to figure out what parameters are passed to the templates you should write.
- Django template tags
including url.
Submitting Your Project to Plussa
Add, commit and push your new files and possible changes to the Git as in round 1.
Finally, just copy and paste your GitLab project's URL to Plussa. The files we will check
are views.py
, countrytable.html
, and continentmenu.html
in exercises/07_django
.