Introduction to view and URL configuration experiments
In the previous chapter, we described how to create a Django project and start the Django Development server. In this chapter you will learn the basics of creating dynamic Web pages with Django. At the same time, we also teach you how to build a separate Python environment on your local machine, and remember to switch to the VIRTUALENV environment using the following commands every time you start working:)
source env/bin/activate
Note that the env in the above command is named after yourself and from this command virtualenv env
, env can be substituted with any name you like.
One, the first Django page: Hello World
Our first goal is to create a Web page that outputs the most famous example: "Hello world."
If you've ever written a simple "Hello World" page without a Web frame, simply type "Hello World" into a text file, save the file as hello.html, and upload it to a directory on your Web server.
Note, however, that in this process you have specified two key messages for this page: its contents (string: Hello world) and its URL ( http://www.example.com/hello.html
if you put the file in a subdirectory, it may also be http://www.example.com/files/hello.html
).
In Django, you also need to specify these two messages, but you have to use different methods. The content of a Web page is generated by the view function, and the URL is specifically configured in the URL configuration (URLconf). First, let's write our "Hello World" view function.
1. First view (views.py)
Go to the previous chapter in the MySite directory (including __init__.py) that we created with django-admin.py Startproject. Create an empty file called views.py. This Python module will contain the view we will write in this chapter. The name of the views.py is not specifically requested, and Django does not require it to be called, but it is customary to call it views.py to make it easier for other developers to read your code.
Our "Hello World" view is simple, it's all about writing defined functions, and importing the package's statements. Enter the content in views.py:
from django.http import HttpResponsedef hello(request): return HttpResponse("Hello world")
Let's step through this piece of code:
First, we import the HttpResponse class from the django.http. We'll use this class in the next step.
Next, we define a view function called Hello.
Each view function must have at least one parameter, which is often called a request. This is an object that contains information about the Web request that triggered the view function, which is an instance of Django.http.HttpRequest (instance). In this case, although we do not do anything with this request, we have to use it as the first parameter of the view.
The name of the view function is not important, and Django does not need it to be named in a particular way. Here we call it hello because Hello clearly indicates the purpose of this view. Of course you can call it Hello_wonderful_beautiful_world or some other sort of disgusting name. The next section, "First urlconf," will explain how Django finds this function.
This function has only a single line of code: it simply returns a HttpResponse object that contains the text "Hello World".
Remember, a view itself is a Python function that takes a httprequest as its first argument and returns an instance of HttpResponse. In order for a Python function to be a Django view, you need to make it meet both of these conditions. (There are exceptions, we'll talk about it later.) )
Second, the first urlconf
Now, if you run again python manage.py runserver
, you'll still see the Welcome page of "Weclome to Django" without seeing the "Hello world" view we just wrote. Because our project MySite is not yet aware of the Hello view, we need to explicitly tell Django which URL to use to activate the view. (as in the example above, we've created the HTML file, but we haven't uploaded it to the server yet.) In Django, to associate the view function to a URL, you need to use URLconf.
URLconf is like the directory of your Django site. Essentially, it is a mapping between a URL and the view function that this URL will call. In this way, you can tell Django: "For this URL, call this code, for that URL, call that code." "For example, when a user accesses/foo/, the View function Foo_view () is called, and the View function is in views.py.
In the previous chapter, when you executed django-admin.py Startproject, Django has automatically created a URLconf for you, which is urls.py that file. The default urls.py will look like this:
Urlconf has a number of annotated features that are often used in Django, and all you can do is turn on these features by simply removing the comments from those features. The following is the actual content after ignoring what is commented out urls.py
:
from django.conf.urls.defaults import patterns, include, urlurlpatterns = patterns(‘‘,)
As usual, let's analyze the code on a row-by-line basis:
The first line imports three functions from Django.conf.urls.defaults. These three functions are the basic constructs of the Django urlconf: patterns, include, and URL. The second line invokes the patterns function and saves the result in a variable called Urlpatterns. The patterns function takes an empty string as an argument. (This string is used as a generic prefix for a view function, and we'll go into Chapter 8:advanced views and Urlconfs.) Note here that Urlpatterns is the variable that Django will look for in your urlconf module. This variable defines the mapping between the URL and the code that handles the URL request. By default, urlconf is blank, and your Django program is a whiteboard piece. (If your urlconf is empty, Django will think the project was just created, so it will show the Welcome page.) )
To add a URL and view to the urlconf, you only need a map of the URL pattern and view function. Here is a demonstration of associating our Hello view:
from django.conf.urls.defaults import patterns, include, urlfrom mysite.views import hellourlpatterns = patterns(‘‘, url(r‘^hello/$‘, hello),)
Note that for brevity, we removed the comment code. If you like, you can keep those lines as well.
We have made two changes:
First, we import the Hello view function from the module mysite/views.py. The import syntax for Python uses mysite.views to represent mysite/views.py. (This code assumes that mysite/views.py is in the Python search path, which is described in more detail in the following comments.) Next, we added the URL (r ' ^hello/$ ', hello) to the urlpatterns. This line is called a urlpattern. The URL () function tells Django how to handle the URL you configured. The first parameter of the URL () is a pattern-matching string (regular expression, which is described in more detail later), and the second parameter deals with the Urlpattern view function. The URL () also accepts the third parameter, which we'll cover in more detail later.
Note Another notable point is that we added an R to the regular expression string. In Python, this represents an original string (raw string), and Python does not escape those backslashes (\). In a normal Python string, backslashes are used to escape special characters, such as the string ' \ n ' is interpreted as a newline character. When you add R, Python will not escape those characters, and R ' \ n ' is a string that includes a backslash and a lowercase letter "n". The use of backslashes in regular expressions is just in conflict with the use of backslashes in Python strings. So it's best to add r when using regular expressions in Python. All the Urlpattern in this book will be in this form.
Simply put, we just told Django that all requests for url/hello/are handled by the Hello view function.
Python's search path (python path) Python's search path refers to the list of system catalogs that Python looks for when you import a statement with import.
For example, if your Python path is set to [' ', '/usr/lib/python2.7/site-packages ', '/home/username/djcode ']. If you execute the statement from Foo Import bar, Python first looks for a module called foo.py in the current directory (the first directory in the Python path, with an empty string representing the current directory). If the file does not exist, Python will continue to look for/usr/lib/python2.7/site-packages/foo.py. If you still can't find it, Python will continue to look for/home/username/djcode/foo.py. Finally, if the file does not really exist, Python throws an exception importerror.
To check your Python path, simply enter it in the Python interaction interpreter:
>> import sys>> print sys.path
Usually you don't have to care about the Python path settings, and Python and Django will handle it for you. (The settings for the Python path in the Django project are controlled by manage.py).
It is also necessary to discuss the syntax of Urlpattern because it is not so intuitive. We want to match the address/hello, but the pattern is different in Urlpattern. Let's take a look at this in more detail:
Django removes the first slash from each URL before checking the URL pattern. This means that the Urlpattern does not include the/hello at the beginning of the slash. (This may not be intuitive at first, but doing so simplifies a lot of things.) )
The matching pattern includes a caret (^) and a dollar character (\$). These two symbols have a special meaning in the regular expression: ^ requires that a match be started from the beginning of the string, and \$ is required to match the trailing string.
It is best to use examples to illustrate. If we don't use the trailing match \$, all URLs beginning with/hello/can match, such as/hello/foo or/hello/bar and/hello. Similarly, if we save the turn-around match ^, Django will match all URLs ending with hello/, such as/foo/bar/hello/. If we omit both characters at the same time, the URLs containing the hello/will match, such as/foo/hello/bar. So, add ^ and \$ is to ensure that only/hello/match, not much also many.
Most Urlpattern will start with a caret (^) and end with a dollar (\$) character. But having the flexibility to match complex URLs can also be good.
You might ask what happens if someone accesses/hello (no trailing slash), because our URL pattern requires a trailing slash at the end so that the URL does not match the pattern we define. However, by default, a URL that does not end with a slash will not find a matching urlpattern, and is redirected (redirect) to the same URL with a slash.
If you are a person who likes all URLs to/from the end (Django developers like this). You only need to add a slash after each URL and set Append_slash to True. If you prefer not to end the slash, or depending on the case of each URL, you need to set Append_slash to False and then add the trailing slash to the URL you want to add, depending on your intention.
Another area to be aware of IS. In this urlconf we are passing the Hello view function directly as an object, rather than calling it. This is an important feature of Pyhton (as a dynamic language), a function is a primary object (first-class objects), and you can pass a function just as you would pass other variables. Pretty cool, huh?
To check the urlconf of our configuration, as in Chapter Two, python manage.py runserver
start the Django Development server. (If you haven't turned off the one you started before, you won't have to start it again.) The Django Development server automatically detects your changes and then loads them automatically without you having to restart them. The development server will run in http://127.0.0.1:8000/
, open a browser, Access http://127.0.0.1:8000/hello/
. You should see your Django view output "Hello world".
For more regular Expressions:
Regular Expressions 30-minute introductory tutorial
Iii. Introduction to the root directory of the website
Now, what do we get when we try to access the root directory of the site http://127.0.0.1:8000/
?
Django doesn't add anything to your site's root directory, and Django doesn't treat this URL differently. This requires you to specify a urlpattern for it in the urlconf, exactly as the other entries in urlconf.
To match the site root directory may not be so intuitive, so here specifically listed here. After you have written the view of your site's root directory, use the ' ^\$ ' mode to match it, because it will match an empty string. As shown in the following example:
from mysite.views import hello, my_homepage_viewurlpatterns = patterns(‘‘, url(r‘^$‘, my_homepage_view), # ...)
1. How Django handles a request
Before we start our second view, I want to pause for a moment and get to the point of the Django principle. When you visit http://127.0.0.1:8000/hello/through a browser, you will see your "Hello World" message. What does Django do in the background?
All starts with the settings file. When you run Python manage.py runserver, the script goes to the inner MySite folder to find a settings.py file. This file wraps up the various configurations of the current Django project. These configuration information is in uppercase, such as: Template_dirs, and DATABASES
so on. One of the most important configurations is root_urlconf. root_urlconf defines which Python module is used as the URLCONF for this site.
Remember when you ran django-admin.py startproject that you created the two files for settings.py and urls.py? This automatically created settings.py includes the root_urlconf and points it to the automated production urls.py. Open this setting.py and you will see:
ROOT_URLCONF = ‘mysite.urls‘
The corresponding file is mysite/urls.py.
When you visit a particular URL, such as/hello/, Django loads the URLCONF that root_urlconf points to, and then checks the Urlpattern in order, until it finds the urlpattern that matches the requested URL. When a matching urlpattern is found, Django invokes the view function associated with the Urlpattern and uploads the current request as a HttpRequest object to the first parameter of the view function. (We will introduce the standard of HttpRequest later.) )
As in our first example, a view function must return a HttpResponse object. The rest is done by Django, which will convert the Python object to the appropriate Web response, setting the appropriate HTTP header and content (such as the content of the Web page).
To summarize:
A request came in, requesting/hello/. Django finds root URLCONF through root_urlconf. Django finds the first urlpattern to match/hello/in urlconf. If a match is found, Django invokes the corresponding view function. The view function returns a HttpResponse. Django converts httpresponse to the correct HTTP response, which is the Web page displayed in the browser. Now you know how to make a Django page. It's really simple, just write some view function and then urlconf them with URL one by one.
Four, second view: dynamic content
Our "Hello World" view is used to demonstrate how Django works, and it is not a dynamic Web page because its content is always the same. Every time you visit/hello/you will see the same content, which is still the same as a static HTML file.
Let's make our second view a little more dynamic, let's make a page that shows the current date and time. This example is simple enough to not involve a database or user input, just to display the time on the server to the page. This example is just a little bit more interesting than the one above, but it can also be used to show several concepts.
This view needs to do two things: calculate the current date and time, and return a httpresponse that contains the value. If you have experience with Python, you might know that Python has a datetime module that can be used to calculate dates. Let's take a look at how to use it:
It's simple, and it doesn't involve Django. It's just the Python code. (We want you to be aware of what is pure Python code, which is a Django-specific code, so you can learn some Python knowledge in the process of learning Django and use it in other Python-free projects.) )
To see our Django view display the current date and time, we just put the statement datetime.datetime.now () into the view function and return a HttpResponse. The code is as follows:
import datetimefrom django.http import HttpResponsedef current_datetime(request): now = datetime.datetime.now() html = "return HttpResponse(html)
If it is not necessary, we will not repeat listing the previous code. You should be able to identify what the previous code is and what the new code is.
Let's review the changes made when we just added Current_datetime.
First, we add a statement to the top of the file, import datetime, so we can calculate the date.
The Current_datetime function calculates the current date and time, and is stored in the Datetime.datetime form in the now local variable.
The second line of the function, we constructed a piece of HTML using the Python formatted string (format-string). The%s in the string is a placeholder, and the percent symbol (%) following the string indicates that the value of the variable now replaces the%s in the preceding string. now
is a datetime.datetime instead of a string, the%s (formatted character) converts it into a string representation of "2014-11-27 17:28:31.002425". So, the end result is an HTML string such as "It's now 2014-11-27 17:28:31.002425."
We have errors in HTML now, and we do this to keep the examples short.
Finally, our view returns a HttpResponse object with just the Hello view, containing the response that was just generated.
After adding a view in views.py, we also add Urlpattern in urls.py to tell Django which URL to handle this view. Using words like/time is easier to understand:
from django.conf.urls.defaults import patterns, include, urlfrom mysite.views import hello, current_datetimeurlpatterns = patterns(‘‘, url(r‘^hello/$‘, hello), url(r‘^time/$‘, current_datetime),)
Here, we have modified two places, first, the Current_datetime function is imported at the top. Then, the more important step is that we add a url/time association to this new view. Do you understand?
Write the view, add the Urlpattern, now run Runserver and access it in the browser http://127.0.0.1:8000/time/
, you will see the current time and date.
But you'll find that time and time are not right, because the default time zone for Django is the birthplace of Django merica/Chicago
, so we can modify the time zone in the settings.py file:
More Time zone options: Http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
Five, third view: Dynamic URL
In our previous view current_datetime, although the content is dynamic, the URL (/time/) is static. In most dynamic Web applications, URLs can often contain parameters that control the output of a page. An online bookstore, for example, assigns a URL to each book, such as/books/243/,/books/81196/.
So let's create our third view, showing the time of the current time plus an offset. Our goal is/time/plus/1/display the current time + 1 hours of the page,/time/plus/2/display the current time + 2 hours of the page,/time/plus/3/display + 3 hours of the page, and so on.
A little bit of advice on pretty URLs
If you have other web platform development experience (such as PHP or Java), you might think: Hey! Let's use the query string parameter! Like/time/plus?hours=3, the hour inside should be specified in the query string by the parameter hours (the part behind the question mark).
You can do this, but one of the core concepts of Django is that URLs must look beautiful. URLs like/time/plus/3/are clearer, simpler, and more readable, and can be easily read aloud. A nice URL is a sign of a high-quality web app.
Django's URL configuration makes it easy to configure beautiful URLs.
So, how do we deal with the deviations of any hour? We're going to use a wildcard character. As we mentioned earlier, a URL pattern is a regular expression, so we can use \d+ to match more than one number here.
urlpatterns = patterns(‘‘, # ... url(r‘^time/plus/\d+/$‘, hours_ahead), # ...)
This urlpattern can match any URL like/time/plus/2/,/time/plus/25/or even/time/plus/100000000000/. Further, let's limit it to the maximum allowable 99 hours, so that we only allow one or two numbers, the syntax of the regular expression is \d{1,2}:
url(r‘^time/plus/\d{1,2}/$‘, hours_ahead),
Note that when we write a web app, it's important to think about possible data entry as much as possible, and then decide which we can accept, and here we show a 99-hour time difference.
We have already configured the wildcard for our URL, and we need to upload its value to the view function so that we can only use one view function to handle any number of time offsets. What we have to do is to enclose the data we need in parentheses in the Urlpattern. In our example, we need that number as a parameter, so we enclose \d{1,2}:
url(r‘^time/plus/(\d{1,2})/$‘, hours_ahead),
After this, let's write the Hours_ahead view.
Hours_ahead is very similar to the one in front of Current_datetime. Only a little different: it also accepts an argument, that is, the offset of the number of hours. The code is as follows:
from django.http import Http404, HttpResponseimport datetimedef hours_ahead(request, offset): try: offset = int(offset) except ValueError: raise Http404() dt = datetime.datetime.now() + datetime.timedelta(hours=offset) html = "return HttpResponse(html)
Let's analyze the code on a row-by-line basis:
View Function:hours_ahead accepts two parameters, request and offset.
The request is a HttpRequest object, just like the previous Hello and current_datetime. Again, a view function must take a HttpRequest object as its first argument.
Offset is a match from the URL. If the requested URL is/time/plus/3/, then offset will be the string ' 3 ', and if the requested URL is/time/plus/21/, then offset will be the string ' 21 '. Note that this capture value is always a string type, not an integer type, even if the string is all composed of numbers (such as ' 21 ').
(more precisely, the captured value will be a Unicode object, not a simple Python string.) But at the moment we don't need to care about this difference)
Here, we call this variable offset, and you can call it any name. The name of the variable is irrelevant as long as it conforms to the Python syntax, as long as it is the second parameter of the view function, after the request. (It is also possible to define it with a keyword instead of a location, which is described in the eighth chapter.) )
In this function, the first thing we do is to raise the offset by an int () and convert it from a string to an integer.
If this value cannot be converted to an integer, Python throws a ValueError exception. (such as int (foo)). In this case, if we encounter valueerror we will throw a django.http.Http404 exception and eventually get a 404 "page not Found" error.
Savvy readers may ask: "We have used the Urlpattern regular expression (\d{1,2}) to constrain it to accept only numbers, how can there be valueerror?" Is it possible to capture a value that is not only made up of numbers? The answer is: we will not do this because Urlpattern provides a "moderate but useful" level of input validation. In case this view function is called by other means, we still need to check the valueerror ourselves. The practice proves that it is better to not speculate the parameter value when implementing the View function. Loosely coupled, remember?
Next line, calculate the current date/time, and then add the appropriate number of hours. In the Current_datetime view, we have seen Datetime.datetime.now (). The new concept here is to perform arithmetic operations on date/time. We need to create a Datetime.timedelta object and add an Datetime.datetime object. The result is stored in the variable dt.
Next, we build the HTML output of this view function. It's almost like we're in current_datetime, but there are two variables in the formatted string. Therefore, there are two%s placeholders in the string, followed by %
a tuple (tuple) of the value to be inserted.
Finally, an HTML HttpResponse is returned. Now, this line of code is no more surprising.
After writing the view function and URL configuration, start the Django Development server and use the browser access http://127.0.0.1:8000/time/plus/3/
to verify that it is working properly. And then it was http://127.0.0.1:8000/time/plus/5/
. And then it's http://127.0.0.1:8000/time/plus/24/
. Finally, access http://127.0.0.1:8000/time/plus/100/
checks to see if the pattern set in the URL configuration accepts only one or two digits, and Django displays a page not found error, just like the 404 error you saw previously. A http://127.0.0.1:8000/time/plus/
404 error will also be thrown when accessing the URL (no time difference is defined).
Encoding order in this example, we wrote the Urlpattern before we wrote the view, but in the previous example we wrote the view first, which is the Urlpattern. Which Way is better?
If you are a person who likes to take a holistic look, you should prefer to write down all URL configurations at the beginning of the project. Then write each of the corresponding views. One of the benefits of this approach is that it gives you a clear list of to-do lists, and explicitly defines the parameters of the view function you need to write.
If you're more like a bottom-up developer, you might prefer to write the view first and then link them to the URL. This is also no problem.
Vi. Summary
In this chapter, we wrote the view function to understand the URL's connection to the view, but we hard-code the HTML directly into the Python code. We do this to demonstrate convenience, but in the actual situation, the general way is not good.
Djano provides a simple but powerful template engine that allows you to separate the design of the page from the underlying code, and we'll delve into the Django template engine in the next chapter.
Homework
Implement when the URL is http://127.0.0.1/sum/n/
(n is a number), the returned page shows the cumulative sum of the 1-n and results.
View and URL configuration