In the previous chapter we explained how to start a Django project and run a Django server
Of course, this site does not actually do anything------except for the information "It worked" is displayed.
In this chapter we describe how to use Django to create dynamic Web pages
Your first view: Dynamic content
Let's create a Web page that displays the current date and time as your first goal
This is an example of a dynamic Web page, because the content of the page varies according to the current time of calculation
This example does not require a database and any user input, just the output server internal clock
We will write a view method, which is just a Python method that accepts a Web request and returns a Web answer
This answer can be HTML content, redirection, 404 error, XML document, Images, and so on. The
view itself contains any necessary logic to return an answer
where the view returns the current date and time as an HTML document
from django.http Import HttpResponse
import datetime
def Current_datetime (Request):
now = Datetime.datetime.now ()
HTML = "It is now%s."% now
return HttpResponse (HTML )
Let's take a look at the code
1, first, we import HttpResponse class from Django.http module
2, then we import the DateTime module from the Python standard library
The DateTime module contains classes and methods that process dates and times, and contains a method that returns the current time
3, then we define the Current_datetime method
This is a view method that uses a HttpRequest object as its first argument
Each view method uses the HttpRequest object as its first argument
In this method, we call this parameter request.
Django doesn't care about the name of the view method, and we don't have to follow a specific naming scheme for Django to identify. We named this method with Current_datetime.
Purely because it precisely expresses the intent of the method, you can name the view method arbitrarily, Current_datetime clearly shows what it will do, and we'll explain how Django found it.
4, the first line of the method calculates the current date and time, and is stored in the local variable now
5, the second line of the method constructs an HTML answer using Python's formatted string capability
The%s inside the string is a placeholder, and the percent semicolon following the string indicates that the value of the now variable is substituted for%s
(For HTML purists: We didn't write doctype, no 6, finally, the view returns a HttpResponse object that contains the generated HTML
Each view method returns a HttpResponse object, with the exception of the case we'll explain later
your first URL configuration
This view method returns an HTML page that contains the current date and time
But where should the code be placed? How do I tell Django to use this code?
The answer to the first question is: You can put the view code anywhere, as long as it is under your Python path, there is no other requirement----No "magic".
We keep the code inside the views.py and put the views.py in the MySite directory
Python path is a directory listing of your system, and Python will look at those directories when you use the Python import statement
For example, your Python path is set to [' ', '/usr/lib/python2.4/site-packages ', '/home/mycode ')
If you execute code from foo import Bar,python will first look for modules called foo.py in the current directory
The first Python path is an empty string, which indicates that the current directory
If Foo.py,python is not found, it will try to find/usr/lib/python2.4/site-packages/foo.py
Finally, if foo.py is still not found, Python will report importerror
If you are interested in viewing Python PATH, enter the python interactive environment and enter import SYS and print Sys.path
Generally you don't have to worry about setting up Python Path,python and Django will silently do these things for you
If you're really curious, setting up Python path is a job for manage.py
How do we tell Django to use these view codes? The answer is URL configuration
Urlconf is like a content table for a Django Web site. Basically, this configuration is a map of the URL pattern and the corresponding view function, which is called when a URL that conforms to a particular pattern is requested.
Urlconf is telling Django, "for this URL, call this code, for that URL, call those code ..."
URL configuration is like the directory of your Django project
Basically, it is the map of the view method called by the URL pattern and the URL pattern
django-admin.py startproject automatically generates a URL profile urls.py, which by default is:
From django.conf.urls import patterns, URL, include
urlpatterns = Patterns ("',
# Example:
# (R ' ^mysite/', include (' Mysite.apps.foo.urls.foo ')),
# uncomment this for admin:
# (R ' ^admin/', Include (' Django.contrib.admin.urls '),
 
Let's take a look at the Code
1, the first line imports all the objects of the Django.conf.urls.defaults module, including a method called Patterns
2, and the second row calls patterns () Method and save to the urlpatterns variable, the patterns () method only passes an empty string as the argument, the other lines are commented out
Here is the variable urlpatterns, which defines the URL and the mapping of the code that handles the URL
By default, all URL configurations are commented out, which means that your Django project is empty, which lets Django know that the "It worked!" is displayed Page
If your URL configuration is empty, Django assumes that you just started a new project so that it displays this message
Let's edit urls.py to expose Current_datetime view:
from django.conf.urls import patterns, URL, include
form Mysite.views import current_datetime
urlpatterns = Patterns (',
The
we made two changes. First, we import the Current_datetime view from the mysite/views.py module
The module is converted to mysite.views in the import syntax of Python
and then we add a line (R ' ^now/$ ', Current_datetime), which points to a URL pattern
This is a python tuple, The first element is a regular expression, the first is the view method
so we tell Django that the request to url/now/should be handled by the Current_datetime view method
Note Several places:
1, in the example, We take the view method Current_datetime as an object instead of calling this method
This is the feature of Python and other dynamic languages, the function is the first class of objects, can be passed like other variables, cool bar?
2, you do not have to add a slash in front of ' ^now/$ ' to match/now/,django automatically precede each expression with a slash
3, ' ^ ', and ' $ ' notation is important, which means "match the starting pattern of a string," which means "a pattern that matches the end of a string "
This example is a good explanation of the conceptual problem, if we use the pattern ' ^now/', then/now/,/now/foo,/now/bar will match
If we use the pattern ' now/$ ' then/now/,/foo/bar/now/and so on will also match
So we use ' ^now/$ ', then not much more than just/now/match
now test our changes to urlconf. Run Python manage.py runserver to start the Django Development Server
(if it keeps running and there is no problem, the server will automatically detect changes to the Python code and reload it if necessary, so there is no need to re-start the change)
Browser Access http://127.0.0.1:8000/now/test the
Hooray! You've developed your first django-powered Web page
How does Django handle request
How does Django handle Web requests? Let's take a look at the truth.
1, Command python manage.py runserver look for settings.py, this file contains all the configuration options for this Django instance
The most important setting is root_urlconf, It tells Django which Python module to use as the URL configuration for the current site
2, when a request comes in as/now/,django loads the URL configuration, and then checks each URL pattern sequentially until a matching URL request pattern is found
Django then invokes that pattern-matching method and passes a HttpRequest object as the first argument
3, the view method is responsible for returning a HttpResponse object
so you know the basics of the Django-powerd page, it's simple, Simply write the view method and map to the URL by URL configuration
URL configuration and loose coupling
Now is a good time to point out the URL configuration and the philosophy behind Django: the loose coupling principle
Loose coupling is a software development method that has the value of making some modules replaceable
If two modules are loosely coupled, then making changes to one module will not or seldom affect the other.
The Django URL configuration is a good example of this principle
In a Django Web program, URL definitions and view methods are loosely coupled, and developers can replace one without having an impact on another
In contrast, other web development platforms are coupled with URLs and programs, such as in basic PHP, where the URL of the application depends on the location of the code in the file system,
In the CherryPy framework, the URL and method names in the app correspond. These methods appear to be very convenient, but in the long run, they can create unmanageable problems.
Consider, for example, the function we just had to show the current time. If we want to change the URL of this app, like from/now/to/currenttime/
We can make a very quick change to the urlconf without worrying about the function implementation that is hidden behind this URL. Similarly, if we want to modify the view function
Modify its logic, we do not need to affect the URL can be done.
Further, if we want to expose this current time method to multiple URLs, we can easily do so by modifying the urlconf without affecting the view's code.
404 Error
In our current urlconf there is only one URL pattern that handles/now/. What happens if we ask for a different URL?
When accessing a URL that is not defined in urlconf, you will see a "page not found" message because the URL is not defined in urlconf.
The purpose of this page is not just to display the 404 error message: It tells us exactly which urlconf the Django uses, and each URL-matching pattern in this configuration.
Through this page we can easily learn why the URL of the request throws a 404 error.
Of course, this information was originally intended to facilitate web developers. If this is an actual Internet site, we do not want this information to be disclosed.
For this reason, this page not found only appears in debug mode.
Your second view: dynamic URL
In the first view example, the current date and time of the page content is dynamic, but the URL ("/now/") is static
In most dynamic web programs, URLs contain parameters that affect the output page
In the following example, we use a number to display the date and time for a few hours.
If/now/plus1hour/shows the next 1 hours,/now/plus3hour/shows the time of the next 3 hours
Modify the URL configuration first:
Urlpatterns = Patterns ("',
(R ' ^now/$ ', current_datetime),
(R ' ^now/plus1hour/$ ', one_hour_ahead),
(R ' ^now/plus2hour/$ ', two_hours_ahead),
(R ' ^now/plus3hour/$ ', three_hours_ahead),
{R ' ^now/plus4hour/$ ', four_hours_ahead),
)
It is obvious that this pattern is flawed and not only produces a large number of view methods, but also limits the program to a predefined hour range.
If we want to show the time after 5 hours, we'll have to add another line.
So we should make a little abstraction here.
About the good URL
If you have used PHP or Java, you might say "Let's use a query parameter," similar to/now/plus?hours=3
You can also use Django to do this, but one of Django's core philosophies is that URLs should be elegant
/now/plus3hours/cleaner, simpler, more readable, and more catchy
A good URL is a display of the quality of the Web program
Django's URL configuration system provides a good URL definition that is easy to configure
URL pattern wildcard characters
To continue our example, let's add a wildcard character to the URL pattern
As mentioned above, the URL pattern is a regular expression, where we can use \d+ to match 1 or more numbers:
From django.conf.urls import patterns, URL, include
From mysite.views import Corruent_datetime, Hours_ahead
Urlpatterns = Patterns ("',
(R ' ^now/$ ', current_datetime),
(R ' ^now/plus\d+hours/$ ', hours_ahead),
)
This URL pattern can match any URL, such as/now/plus2hours/,/now/plus25hours/, or even/now/plus100000000000hours/
, which allows us to limit up to 99 hours, That is, we allow only 1 or 2 numbers, in the regular expression is \d{1,2}:
(R ' ^now/plus\d{1,2}hours/$ ', hours_ahead),
When we build the Web program, consider the possible unreasonable input, and deciding whether to deal with these inputs is very important.
We are here to limit the time offset by <=99 hours. By the way, Outlandishness Curtailers is a super-awesome band. A
regular expression is a concise way to specify patterns in text
The Django URL configuration allows arbitrary regular expressions to provide strong URL matching capabilities, and here are some common patterns:
Java code Replication code
Symbol Matches
. (dot) Any character
\d any number
[A-z] any character from A to Z (uppercase)
[A-z] any character from A to Z (lowercase)
[a-za-z] any character from A to Z (case insensitive)
[^/]+ any character until a previous Slash (without the slash itself)
+ one or more preceding characters
? 0 or more preceding characters
{1,3} 1 to 3 preceding characters (including 1 and 3)
Java Code Collection code
Symbol Matches
. ( Dot) Any character
\d any number
[A-z] any character from A to Z (uppercase)
[A-z] any character from A to Z (lowercase)
[a-za-z] any character from A to Z (case insensitive)
[^/]+ any character until a forward skew Line (without the slash itself)
+ one or more preceding characters
? 0 or more preceding characters
{1,3} 1 to 3 preceding characters (including 1 and 3)
More regular expression information see Appendix 9, Regular Expressions
Well, we've designed a wildcard in the URL, but we need to pass the information to the view method
so we can use a separate view method to handle any hour parameter
We enclose the data we want to save in the URL pattern in parentheses, enclosing \d{1,2}
(R ' ^now/plus (\d{1,2}) hours/$ ', hours_ahead),
If you are familiar with regular expressions, You will feel very gracious: we are using parentheses to get the data we want from the matching text.
The final URL configuration is as follows:
from django.conf.urls.defautls import *
form mysite.views import current_datetime, hours_ahead
urlpatterns = Patterns (',
(R ' ^now/plus (\d{1,2}) hours/$ ', hours_ahead),
)
Below we define the Hours_ahead method:
Caution: About the sequence of encodings
In this example, we define the URL pattern before we begin to write the view code, but in the previous example, the encoding is in the opposite order. So which way is better?
Of course, every developer has a different habit.
If you are a good bigger picture, it is very nice to define all the URL patterns at once and then implement the View Code.
This is a way to show a very clear list of to-do because it fundamentally defines the parameters required for the view function that will be implemented.
If you are a programmer with a bottom-up habit, you might prefer to write a view and then bind it to a URL pattern. It's good to do that.
Both of these methods are certainly correct, depending on which one is more in line with the pattern you are thinking about.
From django.http import HttpResponse
Import datetime
def hours_ahead (Request, offset):
offset = Int (offset)
DT = Datetime.datetime.now () + Datetime.timedelta (hours=offset)
html = "In%s hour (s), it'll be%s."% (offset, DT)
return HttpResponse (HTML)
We're still reading this code one line at a time:
As we did in the current_datetime, we imported the Django.http.HttpResponse and datetime modules
The View function Hours_ahead accepts two parameters: request and offset.
Request is a HttpRequest object, as in Current_datetime. We would like to reiterate that the first argument of each view function always httprequest the object.
Offset is a string whose value is obtained from the requested URL through the parentheses in the URL pattern. For example, the requested URL is/now/plus3hours/
The value of offset is a string ' 3 '. Note that the value obtained from the URL is always a string, not an integer, even if the string is composed of pure digits.
We name this variable offset, but you can name it with any valid Python variable name. The name of the variable is not important, but it must be the second parameter of the view function.
The first thing we do in a function is to call INT () and convert offset into shaping.
If a value cannot be converted to an integer number (like string ' foo '), Python will throw valueerror.
But we are not worried about this because we can be sure that offset must be converted, and regular expression \d{1,2} will definitely get the numbers from the URL.
This also proves from the other side the elegance of urlconf: It provides a fairly clear check of the input.
The next line of the program reveals the reason for the type conversion of offset, which calculates the current time plus a time offset, the value of which is offset
The input parameter required to save the result of the calculation in the variable Dt.datetime.timedelta function is the integer type.
The next line we construct an HTML output, similar to the one in the Current_datetime function.
Finally, as with the Current_datetime function, we return a HttpResponse object.
Well, we'll visit http://127.0.0.1:8000/now/plus3hours/to verify it works.
And then we'll try Http://127.0.0.1:8000/now/plus100hours/,Django. Display "Page not found" error
http://127.0.0.1:8000/plushours/also displays a 404 error because we only accept parameters of 1 or 2 numbers
Django Good error page
We comment out the offset = Int (offset)
# offset = Int (offset)
Then revisit/now/plus3hours and you will see a lot of information on the error page, including the TypeError information on top:
"Unsupported type for Timedelta hours component:str"
What happened?
The Datetime.timedelta function expects the hours parameter to be an integer type, but we commented out the code that converted offset to an integer
This causes Datetime.timedelta to produce typeerror, which is only a small bug that is typically prone to each programmer
Some of the areas that need attention:
1. The top of the page shows the main information about the exception: the type of exception, the parameter of the exception, the number of files and rows that caused the exception
2. The next page shows the complete exception of the Python traceback, where Django displays the file name, method name, number of lines, and the line code in each frame of the stack
By clicking on the dark gray code, you can see a few lines of code before and after the error line, allowing you to get context
Click "Local VARs" to see the list of all local variables, variable values, error points, etc., this debug information is very valuable
3, click "Switch to Copy-and-paste View" under "Traceback" will switch to the version that can be easily copied and pasted
When you want to share unusual information with others or get technical support (Django IRC chat room or Django user mailing list) You can use it very well.
4. "Request Information" includes a large number of information about Web requests that generate errors, get and post information, cookie values and meta information such as CGI headers, etc.
The "Settings" section below lists all the setup information for the current Django installation, which we'll explain slowly later
Django Error page displays richer information in the case of template syntax errors, and now removes the comment offset=int (offset)
Are you the kind of programmer who likes to debug with print statements? This can be done using the Django error page without the print statement
You can temporarily insert the assert false to trigger the error page, and later we'll explain the more advanced debug method
Obviously most of these error messages are sensitive, exposing your Python code and the organs of the Django configuration
It's foolish to show this information online, and a malicious person might do something dirty in your website.
Anyway, we'll talk about how to remove the debug mode later.
Practice
Here are some exercises to solidify the knowledge of this chapter, and here we introduce some new tricks
1, create another view hours_behind, similar to Hours_ahead, except to show the past time offset
This view should be bound to/now/minusxhours/, where x is the number of offset hours
2, once you have finished Exercise 1, a good programmer will find Hours_ahead and hours_behind very similar, it seems superfluous
Merge these two methods into a single method hour_offset,url or keep/now/minusxhours/and/now/plusxhours/unchanged
Don't forget to change the HTML code based on whether the offset is positive or negative, "in X Hour (s)" or "X hour (s) ago"
3, let's be more professional, allow/now/plus1hour/and/now/plus2hours/, but not allow/now/plus1hours/and/now/plus2hour/
4, in the HTML display, if the offset is single digit, use hour, otherwise use hours
Answer
1,hours_behind View:
def hours_behind (Request, offset):
offset = Int (offset)
DT = Datetime.datetime.now ()-Datetime.timedelta (Hours=offset)
html = "%s hour (s) ago, it was%s."% (offset, DT)
return HttpResponse (HTML)
URL pattern:
(R ' ^now/minus (\d{1,2}) hours/$ ', Hours_behind),
2,hour_offset View:
def hour_offset (Request, Plus_or_minus, offset):
offset = Int (offset)
if Plus_or_minus = = ' Plus ':
DT = Datetime.datetime.now () + Datetime.timedelta (hours=offset)
html = ' in%s hour (s), it'll be%s. '% (offset, DT)
Else
DT = Datetime.datetime.now ()-Datetime.timedelta (Hours=offset)
html = '%s hour (s) ago, it was%s. '% (offset, DT)
html = '%s '% html
return HttpResponse (HTML)
URL pattern:
(R ' ^now/(Plus|minus) (\d{1,2}) hours/$ ', Hour_offset),
3,url mode:
(R ' ^now/(Plus|minus) (1) hour/$ ', Hour_offset),
(R ' ^now/(Plus|minus) ([2-9]|\d\d) hours/$ ', Hour_offset),
where "|" Represents "or", the pattern above indicates a matching pattern [2-9] or \d\d
That matches a number from 2 to 9 or two digits.
4,hour_offset View:
def hour_offset (Request, Plus_or_minus, offset):
offset = Int (offset)
If offset = = 1:
Hours = ' hour '
Else
Hours = ' hours '
if Plus_or_minus = = ' Plus ':
DT = Datetime.datetime.now () + Datetime.timedelta (hours=offset)
Output = ' in%s ', it'll be%s. '% (offset, hours, DT)
Else
DT = Datetime.datetime.now ()-Datetime.timedelta (Hours=offset)
Output = '%s '%s ago, it was%s. '% (offset, hours, DT)
Output = '%s '% output
return HttpResponse (Output)
Can't you separate the presentation layer code from the Python code? Oh, this heralds ...
(turn) The third chapter of Django Learning: Dynamic Web Page Basics