(Turn) Chapter 3 of Django Learning: Basics of Dynamic Web Pages

In the last chapter we explained how to start a Django project and run a Django server.
Of course , the site doesn't actually do anything -- other than displaying the "It worked" message.
In this chapter we describe how to create dynamic web pages with Django

Your first view: dynamic content
Let's create a web page that displays the current date and time as your first target.
This is an example of a dynamic web page, because the page content changes based on calculating the current time.
This example does not Requires database and any user input, just outputs the server internal clock
We 'll write a view method, which is just a Python method, that accepts a web request and returns a web response
. The response can be HTML content, redirects, 404 errors, XML documents, images, etc. etc. The
view itself contains any necessary logic to return the response
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 code
  1, first, we import the HttpResponse class 2 from the django.http module
  , then, we import the datetime module from the Python standard library The
    datetime module contains some classes and methods that deal with dates and times, and contains a method that returns the current time method
  3, then, we define the current_datetime method
    This is a view method that takes an HttpRequest object as its first parameter
    Each view method takes an HttpRequest object as its first parameter
    In this method, we put This parameter is called request
    Django doesn't care about the name of the view method, and we don't have to follow a specific naming convention for Django to identify. We named this method current_datetime
  purely because it just happens to express the intent of the method. You can name the view method whatever you want, and current_datetime makes it clear what it will do. We'll explain how Django finds this method in a bit.
  4 The first line of code in this method calculates the current date and time and stores it in the local variable now5.
  The second line of code in this method uses Python's formatting string capabilities to construct an HTML response
    string where %s is a placeholder character, the percent sign after the string means to use the value of the now variable instead of %s
    (for html purists: we didn't write a DOCTYPE declaration, no <head> tag, etc., etc., we just try to keep this page as concise as possible .)
  6. Finally, the view returns an HttpResponse object containing the generated HTML.
    Each view method returns an HttpResponse object, with exceptions that we will explain later

Your first URL configures
this view method to return an HTML page with the current date and time
but where should this code go? How do I tell Django to use these codes?
The answer to the first question is: you can put the view's code anywhere, as long as it's on your Python PATH, without any other requirements -- no "magic".
We save this code in views.py and put views.py in the mysite directory
Python PATH is a list of directories on your system that Python will look in 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 the code from foo import bar, Python will first look in the current directory for a module called
foo.py A Python PATH is an empty string, which means the current directory
If foo.py is not found, Python will try to find /usr/lib/python2.4/site-packages/foo.py
Finally, if foo.py is still not found , Python will report an ImportError.
If you are interested in checking the Python PATH, go into the Python interactive environment and type import sys and print sys.path
In general
you Curious, setting the Python PATH is a job of manage.py
How do we tell Django to use these view codes? The answer is that the URL configuration
URLConf is like a table of contents for a Django web site. Basically, this configuration is a map of URL patterns and corresponding view functions that will be called when a URL matching a specific pattern is requested.
A URLconf is all about telling Django, "For this URL, call this code, for that URL, call that code..." A
URL config is like a directory for your Django project.
Basically , it's the URL pattern and the view methods that the URL pattern calls. The mapping of
django-admin.py startproject will automatically generate a URL configuration file urls.py, by default it is like this: 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 this code
1, the first line imports all objects of the django.conf.urls.defaults module, including a method called patterns
2, the second line calls the patterns() method and saves it to the urlpatterns variable, The patterns() method only passes an empty string as a parameter, and other lines are commented out. The main thing
here is the variable urlpatterns, which defines the mapping between URL and URL processing code.
By default, all URL configurations are commented out. This means that your Django project is empty, which tells Django to display the "It worked!" page
If your URL configuration is empty, Django assumes you've just started a new project and displays this message.
Let's Edit urls.py to expose the current_datetime view:

from django.conf.urls import patterns, url, include
form mysite.views import current_datetime

urlpatterns = patterns('',
(r'^now/$', current_datetime),
)
we did Two changes. First, we import the current_datetime view from the mysite/views.py module 

The module is converted to mysite.views in Python's import syntax
and we add a line (r'^now/$', current_datetime) which points to a URL pattern
which is a Python tuple, the first element is a regular expression The first is the view method. In
this way , we tell Django that the request for the URL /now/ should be handled by the current_datetime view method.
Note a few things:
1. In the example, we pass the view method current_datetime as an object instead of calling this Methods
This is a feature of Python and other dynamic languages, functions are first-class objects and can be passed like any other variable, cool?
2. It is not necessary to add a slash in front of '^now/$' to match /now/, Django automatically adds a slash in front of each expression
3, '^' and '$' symbols are very important, the former means "matching string pattern at the beginning", the latter means "pattern that matches the end of the string"
This example explains the conceptual problem well, if we use the pattern '^now/', then /now/, /now/foo, /now/bar are all will match
if we use the pattern 'now/$' then /now/, /foo/bar/now/, etc. will also match
so we use '^now/$', nothing more, no less only /now/ matches
now test Our modifications to URLConf. Run python manage.py runserver to start Django's development server
(it's fine if you keep it running, the server will automatically detect changes to the Python code and reload if necessary, so there's no need to restart as soon as you make changes)
Browser visit http://127.0.0.1:8000/now/ and test it
Hooray ! You have developed your first Django-powered web page

How
does Django handle requests? How does Django handle web requests? Let's take a look at the
facts
Configuration
2. When a request comes in like /now/, Django loads the URL configuration, then checks each URL pattern in order until it finds a matching URL request pattern,
then Django calls the method that matches that pattern, passing an HttpRequest object as the first One parameter
3. The view method is responsible for returning an HttpResponse object
So you understand the basics of Django-powerd pages, it's very simple, just write the view method and map it to the URL through the URL configuration

URL Configuration and Loose Coupling
Now is a good time to point out URL Configuration and the philosophy behind Django: Principles of
Loose Coupling Loose Coupling is a software development approach
that has the value of making some modules replaceable Making changes that will have little or no impact on the other
Django's URL configuration is a good example of this principle.
In Django web applications, URL definitions and view methods are loosely coupled, and developers can replace one without compromising on the other. Another has an impact. In
contrast , other web development platforms couple URLs and programs. For example, in basic php, the URL of the application depends on the location of the code in the file system.
In the CherryPy framework, the URL and the method name in the application is corresponding. These approaches seem very convenient, but can cause unmanageable problems in the long run. For
example , consider the function we just showed that displays the current time. If we want to change the URL of this application, for example from /now/ to /currenttime/
we can make a very quick modification to the URLconf without worrying about the function implementation behind the URL. Similarly, if we want to modify the view function and
modify its logic, we can do it without affecting the URL.
Further, if we want to expose the current time method to multiple URLs, we can do it easily by modifying the URLconf without affecting the view code.

404 errors
There is only one URL pattern in our current URLconf that handles /now/. What happens if we request a different URL?
When visiting a URL that is not defined in URLconf, you will see a "Page not found" message because the URL has not been defined in URLconf.
The purpose of this page is not just to display a 404 error message: it tells us exactly which URLconf is used by Django, and every URL matching pattern in that configuration.
From this page we can easily see why the requested URL throws a 404 error.
Of course, this information was originally intended as a convenience for web developers. If this is an actual internet site, we don't want this information to be leaked.
For this reason, this "Page not found" page is only displayed 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 Page Parameters In
the following example, we use a number to display the date and time in hours. For
example, /now/plus1hour/ displays the next hour, and /now/plus3hour/ displays the next 3 hours.
First modify the URL configuration:

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),
)

Obviously such a pattern is flawed, not only will it generate a lot of view methods, but it will confine the program to a pre-defined hour range
If we want to display the time after 5 hours, we have to add one more line
so we should make a little bit here abstract

About good URLs
If you've used PHP or Java, you might say "let's use a query parameter", something like /now/plus?hours=3
You can also do this with Django, but a core philosophy of Django Yes, URLs should be elegant
/now/plus3hours/ cleaner, simpler, more readable, and more catchy A
good URL is one of the qualities of a web program that shows
Django's URL configuration system provides good URL definitions that are easy to configure

URL Pattern Wildcards
Continuing with our example, let's add a wildcard to the URL pattern As mentioned
above , the URL pattern is a regular expression, here 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/
let's limit up to 99 hours, i.e. we only allow 1 or 2 numbers, in the regex It is \d{1,2}:
(r'^now/plus\d{1,2}hours/$', hours_ahead),
when we build web programs, consider possible unreasonable inputs, and decide Whether or not these inputs are handled is very important.
We limit the time to offset <= 99 hours here. By the way, the Outlandishness Curtailers are a great band.
Regular expressions are a concise way of specifying patterns in text.
Django's URL configuration allows arbitrary regular expressions to provide powerful URL matching capabilities. Here are some commonly used patterns:
Java Code Copy Code
Symbol Matches
.(dot) Any character
\d Any digit
[AZ] Any character from A to Z (uppercase)
[az] Any character from a to z (lowercase)
[A-Za-z] Any character from a to z (case-insensitive)
[^/]+ any character up to a forward slash (excluding the slash itself)
+ one or more preceding characters
? Zero or more preceding characters
{1,3} between 1 and 3 preceding characters Characters (including 1 and 3)
Java Code Favorite Code
Symbol Matches
.(dot) Any character
\d Any digit
[AZ] Any character from A to Z (uppercase)
[az] Any character from a to z (lowercase)
[A-Za-z] Any character from a to z (case-insensitive)
[^/]+ any character up to a forward slash (excluding the slash itself)
+ one or more preceding characters
? Zero or more preceding characters
{1,3} between 1 and 3 preceding characters characters (including 1 and 3)

For more information on regular expressions 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 that we can use a single view method to handle arbitrary Hours parameter
We enclose the data we want to save in the URL pattern in parentheses, that is, enclose \d{1,2}
(r'^now/plus(\d{1,2})hours/$', hours_ahead),
if you're familiar with regular expressions, you'll find it very familiar: we're using parentheses to get the data we want from the matched 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/$', current_datetime),
(r'^now/plus (\d{1,2})hours/$', hours_ahead),
)
Next we define the hours_ahead method: 

Caveat: About the order of encoding
In this example, we define the URL pattern first, and then start writing the view code, but in the previous example, the order of encoding is reversed. So which way is better?
Of course, every developer has different habits.
If you're a big-picture person, it's great to define all the URL patterns at once, and then implement the code for the view.
This approach can present a very clean to-do list because it basically defines the parameters required by the view function that will be implemented.
If you are a programmer with a bottom-up habit, you may prefer to write a view and bind it to a certain URL pattern. It's not bad to do so.
Both ways are of course correct, and which one to use depends on which is more in line with your mode of thinking.

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 will be %s." % (offset, dt)
return HttpResponse(html)

Let's decipher the code one line at a time:
as we did in current_datetime, we imported django.http.HttpResponse and the datetime module's
view function hours_ahead accepts two parameters: request and offset.
request is an HttpRequest object, as in current_datetime. Let's reiterate: the first parameter of every view function is always the HttpRequest object.
offset is a string whose value is obtained from the requested URL via the pair of 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 and not an integer, even if the string consists of pure numbers.
We named this variable offset, but you can name it any legal Python variable name. The name of the variable is not important, but must be the second parameter of the view function.
The first thing we do in the function is to call int() to convert the offset to an integer.
If a value cannot be converted to an integer (like the string 'foo'), Python will throw a ValueError.
But we're not worried about that, because we can be sure that the offset must be converted, and the regular expression \d{1,2} must get the number from the URL.
This also proves the elegance of URLconf from another aspect: it provides a check on the input quite clearly.
The next line of the program reveals the reason for the type conversion of the offset. This line of code calculates the current time plus a time offset. The value of this offset is the offset
The input parameter required to save the result of the calculation in the variable dt.datetime.timedelta is an integer.
On the next line we construct an html output similar to the current_datetime function.
Finally, like the current_datetime function, we return an HttpResponse object.
Well, we visit http://127.0.0.1:8000/now/plus3hours/ to verify that it works
and then we try http://127.0.0.1:8000/now/plus100hours/, Django shows "Page not found" The error
http://127.0.0.1:8000/plushours/ will also show a 404 error because we only accept parameters of 1 or 2 numbers

Django's good error page
We comment out offset = int(offset)
# offset = int(offset)
and revisit /now/plus3hours, you will see an error page with a lot of information, including the TypeError message at the top:
"unsupported type for timedelta hours component: str"
what happened?
The datetime.timedelta function expects the hours parameter to be of type integer, but we commented out the code that converts the offset to an integer.
This results in a TypeError for datetime.timedelta, which is just a typical little bug that every programmer is prone to.
Some of the things to pay attention to:
1. The top of the page displays the main information about the exception: the type of exception, the parameters of the exception, the file and line number that caused the exception
2. The next page displays the complete Python traceback of the exception, in each frame of the stack Django All show the file name, method name, line number and the line of code
Click on the dark gray code, you can see a few lines of code before and after the error line, allowing you to get the context
Click "Local vars" to see all the local variables Lists, variable values, error points, etc., this debug information is very valuable
3. Click "Switch to copy-and-paste view" under "Traceback" to switch to a version
that It can be used very well when others share unusual information or get technical support (Django IRC chat room or Django user mailing list)
4. "Request information" includes a lot 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 settings information for the current Django installation, followed by We will slowly explain that these
Django error pages will display richer information in case of template syntax errors, etc. Now uncomment offset=int(offset)
Are you the kind of programmer who likes to debug with print statements? You can do this with Django
error pages, no print statements needed
The innards of your Python code and Django configuration. It's stupid to
put this information on the Internet, and malicious people may do dirty things in your website.
Anyway, we will talk about how to remove debug mode later.

Exercises
Here are some exercises to consolidate the knowledge of this chapter, we introduce some new tricks here
1, create another view hours_behind, similar to hours_ahead, but show the past time offset
This view should be bound to /now/minusXhours /, where X is the offset hours
2, once you've done exercise 1, a good programmer will find that hours_ahead and hours_behind are very similar, which seems redundant Combine
these two methods into a single method hour_offset, URL Or keep /now/minusXhours/ and /now/plusXhours/ the same
Don't forget to change the HTML code depending on whether the offset is positive or negative, "In X hour(s)" or "X hour(s) ago"
3, let We are a bit more professional, allowing /now/plus1hour/ and /now/plus2hours/, but not allowing /now/plus1hours/ and /now/plus2hour/
4. In HTML display, if the offset is a single digit, use hour , otherwise use hours

答案
1,hours_behind视图:

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模式:

(r'^now/minus(\d{1,2})hours/$', hours_behind),

2,hour_offset视图:

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 will 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模式:

(r'^now/(plus|minus)(\d{1,2})hours/$', hour_offset),

3,URL模式:

(r'^now/(plus|minus)(1)hour/$', hour_offset),
(r'^now/(plus|minus)([2-9]|\d\d)hours/$', hour_offset),

Where "|" means "or", the above pattern means matching the pattern [2-9] or \d\d
, that is, matching a number from 2 to 9 or matching two numbers
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 %s, it will 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 we separate the presentation layer code from the Python code? Hehe, that foreshadows...

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325387288&siteId=291194637