**************
URLs and Views
**************
Now you can start to build the frontend for the marcador app. In this
chapter two URLs and their corresponding views will be created. The
first is a simple list view of all public bookmarks, the second is a
list of all bookmarks from a particular person.
.. index:: URLconf
Configure the URLs
==================
"A clean, elegant URL scheme is an important detail in a high-quality Web
application. Django lets you design URLs however you want, with no
framework limitations."
-- :djangodocs:`URL dispatcher | Django documentation `
So that the views can be used, paths must be associated with them. In Django,
this is done explicitly with a URL configration (URLconf). We'll create a new
URLconf just for the marcador app, so that later on the project will have a
cleaner structure.
Add URLs to the application
---------------------------
Create a new file named :file:`urls.py` in the directory
:file:`mysite/marcador` and paste in the following lines:
.. _first-urlconf:
.. literalinclude:: ../src/mysite/marcador/urls.py
:lines: 1-6, 11-13
:linenos:
Every URLconf must define a variable ``urlpatterns`` which is a list of URLs.
Each URL will be created with the ``url()`` function. In our example ``url()``
is given three parameters: the path, the names of the views, and an identifier
(name), with which you can refer to this URL later. In the documentation you'll
find a list of :djangodocs:`further parameters
[`.
With Django the paths are defined as Regular Expressions (regexes). Regexes are
a powerful tool with which to describe strings of characters by means of
syntactic rules. You can find a detailed introduction to this theme at
`regular-expressions.info `_. The `Online
regex tester and debugger `_ can help you to craft
regular expressions for new URLs.
The regex for the list view, ``r'^$'``, consists of the control
characters ``^`` (the beginning of the string) and ``$`` (the end of the
string). When nothing is in-between these two characters, they describe
an empty string. That means that the view is reachable from the path
``/``, the home page.
The regex for the view with the bookmarks of a particular user is a bit
more complex: ``r'^user/(?P[-\w]+)/$'``. It contains a
variable part that enables the user names to be filtered out. So with
``/user/alice/`` the bookmarks from Alice can be requested, and with
``/user/bob/``, the bookmarks from Bob.
The regexes are composed as follows: after the control character for the
beginning ``^`` comes ``user/``, a static part that must match exactly.
Then follows a grouping ``(?P[-\w]+)``. This means that all
the following letters, numbers, underscores and dashes (defined by
``[-\w]+``) can be accessed using the variable ``username``. Django
makes sure that all groupings are passed to the view as arguments. At
the end is the static part ``/`` and the control character for the end
of the string ``$``. With Django it's conventional for all paths to end
with a ``/``.
Add URLs to the project
-----------------------
So that the URLconf for our app can be found, it must be referenced in the root
URLconf. So paste the emphasized line into the file
:file:`mysite/mysite/urls.py`:
.. literalinclude:: ../src/mysite/mysite/urls.py
:lines: 1-17, 19-22, 27
:linenos:
:emphasize-lines: 21
Test the new URLs
-----------------
Now you can visit both URLs in your browser:
* http://127.0.0.1:8000/
* http://127.0.0.1:8000/user/admin/
For both URLs a ``ViewDoesNotExist`` exception will be raised. This
means that the URLs were correctly resolved, but the associated views do
not exist.
.. index:: Views
Add the views
=============
"A view function, or view for short, is simply a Python function that takes
a Web request and returns a Web response."
-- :djangodocs:`Writing views | Django documentation `
The next step is to add the views. In Django a view is a function that
receives a request object and returns a response object. The function
contains the logic that determines the content of the response.
A view to display all bookmarks
-------------------------------
The first view gives a list of the public bookmarks. Open the file
:file:`views.py` in the directory :file:`mysite/marcador/` and paste the
following code in:
.. literalinclude:: ../src/mysite/marcador/views.py
:lines: 4-5, 7-13
:linenos:
First of all the database query for all public bookmarks is be generated
by means of the ORM, and assigned to the variable ``bookmarks``. This is
then in turn stored in the dictionary ``context``. All keys in this
dictionary will later be available to the templates as variables.
Finally the function ``render()`` generates the response object from the
request, the path to the template and the dictionary. ``render()`` is a
shortcut, that carries out several steps in one. You'll need the
shortcuts ``get_object_or_404()`` and ``redirect()`` for the following
views. You can find out what exactly the shortcuts do in the
:djangodocs:`documentation `.
.. _bookmark_user:
A view for each user
--------------------
The second view lists all public bookmarks from a particular user. The
new rows that you must paste in are highlighted:
.. literalinclude:: ../src/mysite/marcador/views.py
:lines: 2, 4-5, 7-23
:linenos:
:emphasize-lines: 1, 13-20
It has an additional argument ``username``, with which the requested user in
the database is sought. This contains the same variable as in the :ref:`regex
of the URLconf `. If the user is not found, the HTTP status code
404 will be returned automatically. Whether the user exists and whether he or
she is the logged-in user is checked with the help of the :ref:`relationship
`, defined by the field ``Bookmark.owner`` with the model
``User``, and the bookmarks loaded. If the view for another user is invoked,
the public bookmarks are filtered with the help of the argument ``username``.
Bookmarks and user are then added to the context dictionary, so that they can
be accessed in the template later.
Test the new views
------------------
You can now test both URLs:
* http://127.0.0.1:8000/
* http://127.0.0.1:8000/user/admin/
Of course both currently produce a ``TemplateDoesNotExist`` exception, because
the templates do not yet exist. Notice that the second URL will only work if
you have an user named "admin". Otherwise use the username of the superuser you
created when you ran the :ref:`createsuperuser ` command.
]