Your First View

Project Files

The following code examples assume you have created your project and app files with the startproject and startapp utilities. It’s recommended you use this default structure throughout the book so your code matches the examples. Also note, the code in this book was written in Django 3.0, so the default file contents may be slightly different if you are using Django 2.2 or a later version of Django 3.

To create our first view, we need to modify the views.py file in our events app (changes in bold):

  1. # \myclub_root\events\views.py
  2. 1 from django.shortcuts import render
  3. 2 from django.http import HttpResponse
  4. 3
  5. 4 def index(request):
  6. 5 return HttpResponse("<h1>MyClub Event Calendar</h1>")

Let’s examine this code closely:

  • Line 1. Import the render() method. startapp adds this line to the file automatically. render() is used when rendering templates, which we will cover in Chapter 6.
  • Line 2. We import the HttpResponse method. HTTP, the communication protocol used by all web browsers, uses request and response objects to pass data to and from your app and the browser. We need a response object to pass view information back to the browser. We cover request and response objects in Chapter 10.
  • Lines 4 and 5. This is your view function. It’s an example of a function-based view. It takes a request from your web browser and returns a response. In this simple case, it’s just a line of text formatted as an HTML heading.

Configuring the URLs

If you started the development server now, you would notice it still displays the welcome page. For Django to use your new view, you need to tell Django the index view is the view you want to display when someone navigates to the site root (home page). We do this by configuring our URLs.

In Django, the path() function is used to configure URLs. In its basic form, the path() function has a very simple syntax:

  1. path(route, view)

A practical example of the basic path() function would be:

  1. path('mypage/', views.myview)

In this example, a request to http://example.com/mypage would route to the myview function in the application’s views.py file. Don’t worry if this is a bit confusing now; it will make a lot more sense once you have written more views.

The path() function also takes an optional name argument, and zero or more keyword arguments passed as a Python dictionary. We will get to these more advanced options later in the book.

The path() function statements live in a special file called urls.py.

When startproject created our website, it created a urls.py file in our site folder (\myclub_site\urls.py). This is the correct place for site-wide navigation, but is rarely a good place to put URLs relating to individual applications. Not only is having all our URLs in the one file more complex and less portable, but it can lead to strange behavior if two applications use a view with the same name.

To solve this problem, we create a new urls.py file for each application. If you are wondering why startapp didn’t create the file for us, not all apps have public views accessible via URL. For example, a utility program that performs background tasks would not need a urls.py file. For this reason, Django lets you decide whether your app needs its own urls.py file.

First, we need to create a urls.py file in our events app (new file):

  1. # \myclub_root\events\urls.py
  2. 1 from django.urls import path
  3. 2 from . import views
  4. 3
  5. 4 urlpatterns = [
  6. 5 path('', views.index, name='index'),
  7. 6 ]

Let’s look at this code closer:

  • Line 1 imports the path() function. This import is necessary for the URL dispatcher to work and is common to all urls.py files.
  • Line 2 imports the local views.py file. The dot operator (“.”) in this case is shorthand for the current package, so this is saying “import all views from the current package (events)”.
  • Line 4 lists the URL patterns registered for this app. For readability, the list is broken into multiple lines, with one URL pattern per line.
  • Line 5 is the actual URL dispatcher:
    • '' matches an empty string. It will also match the “/” as Django automatically removes the slash. In other words, this matches both http://example.com and http://example.com/.
    • views.index points to our index view. I.e., the dot operator is pointing to the index view inside the views.py file that we imported in line 2.
    • name='index'. While it’s optional, you should always name your URLs. We name URLs so they can be referred to in code (reverse lookup). URL reversing is common in both templates and views, so you will see several examples as we work through the book.

Now let’s look at the site urls.py file (changes in bold):

  1. # \myclub_site\urls.py
  2. 1 from django.contrib import admin
  3. 2 from django.urls import include, path
  4. 3
  5. 4 urlpatterns = [
  6. 5 path('admin/', admin.site.urls),
  7. 6 path('', include('events.urls')),
  8. 7 ]

We have made two important changes to the file:

  • Line 2. We have added the include() function to our imports.
  • Line 6. We have added a new URL dispatcher. In this file, the dispatcher is including the urls.py file from the events app. The empty string ('') will match everything after the domain name. This pattern must be the last entry in the urlpatterns list, otherwise Django’s shortcut logic will switch to the events app before trying to match any of the other site URLs.

If you now run the development server and navigate to http://127.0.0.1:8000/ in your browser, you should see a plain, but functioning home page (Figure 5-1).

Your First View - 图1

Figure 5-1: A plain, but functioning homepage for your website.

So What Just Happened?

To better understand how Django works, let’s build on the generic example from Chapter 3 with a concrete example of what Django did to display our home page:

  1. Our browser sent a message to the Django development server requesting it return content located at the root URL (http://127.0.0.1:8000/).
  2. Django then looked for a URL pattern matching the request, by first searching the site level urls.py, and then each of the apps for a urls.py file containing a pattern that matches.
  3. Django checks the first pattern (admin/) in our site level urls.py which doesn’t match and moves on to the second line in which the empty string (root URL) matches.
  4. The matching pattern includes the urls.py from the events app. Basically, this include says “go look in the events app for a pattern that matches”.
  5. Once in the app-level urls.py, the empty string matches again. But this time, the request is sent to the index view.
  6. The index view then renders our simple HTML message to a HttpResponse and sends it to the browser.
  7. The browser renders the response and we see our page heading.

Every Django application follows this same basic process each time it receives a request from the browser.