 A view module is expressed in Web2Py's special template syntax, and by a few simple rules, Web2Py will take that view file and translate it into a module of ordinary Python code. So first off, any text in a view which is inside a pair of double braces, that is taken as verbatim Python code. It's one or more lines of Python code. However, there's an exception whereby if the first character inside the double braces is an equal sign, then the text that follows should be a single Python expression, and these double curly braces are translated into a single line of response.write with expression as the first argument and the escape argument given the value true. As for all the text outside of double curly braces, each contiguous chunk between the pairs of curly braces is translated into the single line of Python response.write with the chunk of text as the string argument to write and escape set to false. In other words, that whole chunk of text is going to be written out to the response body verbatim without escaping. Lastly, to make up for the fact that in this templating syntax, we're not observing the normal rules of Python indentation, we have to make sure that every block of Python code, every if block, every else block, etc., has a logical terminator. Therefore every block has to end with either a return, raise, or pass statement. The pass statement recalls a special Python statement that does nothing. So most commonly you'll just put a pass statement at the end of say your if blocks to indicate this here indicates the end of this if. So with these four rules in mind, say we have a view file with this content. When this gets translated into Python, all of the chunks of text outside the pairs of double curly braces becomes a single line of Python code that invokes response.write with that text as the argument. And the text inside each pair of curly braces gets taken verbatim as one or more lines of Python code. So on first pass, this is what we end up with, but notice this isn't yet proper Python because it doesn't have Python indentation. Because however we included the pass statement to indicate the termination of the if else block, Web2py can infer the indentation. And so this is the end result. Notice that without the pass statement here, Web2py wouldn't know whether or not the last response dot write line, whether that's supposed to be part of the else block or not. If we didn't include this pass statement, the view would be no good because the code would be ambiguous, and Web2py would give us an error. Now, this is something I mentioned only in passing, so it's good to state here again, and that is that in a view module, Web2py automatically imports into that view module's namespace. First, every key value pair that was returned by the action, like say, if the action returns a dictionary with a key of the string foo and the value three, that's going to become a variable foo with a value three in the view. And the view doesn't have to import anything because it's just thereby magic, because as we described earlier, Web2py doesn't import modules normally, it uses the special exec statement and the built-in function exec file. And aside from that dictionary, views also have access to all of things that were defined in the model modules, which we haven't discussed yet, but any name we assign in those modules, we can access that stuff in our views, if we like. In other words, the module namespace of those model modules is visible inside any view. The view temple syntax is slightly more complicated than I let on because it also contains what are called directives. There's just a handful of these, and they're written inside double curly braces, but they're not lines of Python code that begin with the word include or the word extend. When you see the include directive written with a file path in quote marks, that is a standalone directive that just works by itself, whereas if you see an include directive without any file path, that's used in conjunction with the other directive called extend. So first off, here's what the include directive does when we specify a file path. We have two separate view files here, the first my page.html, and the other called other view.html. And in the my page view, there's an include directive, which specifies a file path pointing to the other view file. And note that it's a relative path relative from the views directory. The effect of this include directive when we render my page.html, the content of the other view, which we're pointing to, other view.html, that gets inserted in place. So the content of other view.html is inserted in place of where the include directive was. Now with this form of the include directive, it makes sense that you can include in your view multiple include directives. When it comes to the other include directive, the include form that doesn't have any file specified, that form is used in conjunction with extend. And include and extend, you would only include once. The way that the file was form of include and the extend directive worked together is that in one view, the view that we're going to render, here my page.html, we use an extend directive and we have it specify the path to the other view file, here master template.html, which is directly in the views directory. And in the master template.html view, we place a single include directive with no file specified. What happens then when we render my page.html, which contains the extend directive, is the other template specified in the extend directive here master template.html. The content above its include directive, it's inserted in place where the extend directive was and the content below the include directive gets appended to the end. And be absolutely clear here, we're talking about modifying the rendered output, not modifying the actual view files. Now the way I just explained this is how I prefer to think of how extend and include work together. The other way to think of it, though, is that it works in the opposite direction where the content of my page, the stuff above the extend is being inserted at the top in the other template and the stuff below extend is being inserted where include goes. But whichever way you think of it, the rendered output comes out the same. Now the intended purpose of extending include is that we can create a template file in which we place the include directory and then we can create various other views which all extend that one template. So most commonly for a site, you create a template file that defines the header and the folder that you want to see on every single page and also includes default style stuff like defining the margins on the sides and so forth and defining what the background should look like. And then where you have the include directive, that's the content area where you plug in the specific content for specific pages. So in the views for our specific pages, we place the stuff we want to get inserted there below the extend directive. The purpose of allowing stuff to go above the extend directive and thereby remain at the top of the rendered output, the intended use of that is mainly not to put actual content, text content that's going to be in the final output, but rather to put lines of Python code which define things of certain names. That way we can have a master template that makes use of variable names which the template expects to have provided by the specific page which is extending the template. So say if the template file makes use of some function named foo, which in itself does not define, well, what's going on there is it's expecting the extending view to define a function foo above the extend directive. That way the function foo will exist before it gets called. So the template view made use of something which it left up to the extending view to define. That way the different extending views can define it in different ways. As in other convenience, Web2py provides what it calls HTML helper types. These are essentially Python classes which represent the various elements that make up an HTML document. Each class represents a different kind of HTML tag. So there's the type A, capital A for an anchor tag, P for paragraph tag, div for a div tag, span for span, form for form, input it for an input, et cetera, including basically all the commonly used HTML tags. So here are a few examples. First we're creating an object representing an anchor tag and the content of that tag is passed as the first argument is a string. And then any attributes to the tag are passed as named arguments. But notice the named argument starts with an underscore. So to set the href, we have a named argument underscore href. So this invocation of the A class returns a new object representing an anchor with an href of http equals slash slash yahoo.com and the text content, a search engine. So the common pattern with these helper types is that the positional arguments we pass to them, those become the content to the tag. And if we want to set any attributes, we pass those as named arguments with an underscore at the start. So here in the second example, we're creating a div object, and we're passing to it three positional arguments, two of which are other helper objects. They are P tag objects, paragraph tags. And so what we end up with is a div with the content of first a P tag containing the text, blah, blah, because that's what was passed to the first P tag. And then the text content, hello. And then another P tag, also with text content reading, blah, blah. Now an important thing to understand here is a string argument is treated as text content. So it is effectively XML escaped. Here we're going to create a div and pass in a single string containing what looks like a tag, but no. These angle brackets, the less than and greater than signs, they get XML escaped into character entities. Now usually what we do with these helper objects is we ultimately render them back into text when we use them in a view. And this is done with the method, which is rather strangely named XML. So here, for example, when we invoke the XML method on this div helper object, what we get back is a string reading div, P, blah, blah, NP, and div, which is what you would expect because that's the HTML represented by this object. And again, be clear that the strings we pass to these helper object constructors, they're always treated as text content that needs to be XML escaped. So here when we pass to div this string that looks like it contains a P tag, well, no. That's not parsed into a P tag. It's just treated as text content. So when we invoke the XML method on this div object, the string we get back, yes, there's a div tag, but then inside are a bunch of character entities where the angle brackets were. There's another useful helper object which does not represent an HTML tag, but rather just represents actually any text we want, any text that we don't want to get XML escaped. And kind of strangely, this helper type is called XML because, well, it is useful for representing XML, but it's also useful for representing any other text, like, say, maybe JavaScript code. But here, for example, we're creating an XML object, and its content actually is proper XML. And notice that it's not getting escaped. So when we call the XML method on this XML helper object, what we get back is a string with the verbatum content. Now, you're probably wondering, well, why does this thing exist? Because all it's doing is wrapping a string, and then when we call the main method of this object XML, we're just getting that string back. So what's the point? Well, the XML type has optional features we can use to sanitize the text. To be sure, for example, that the text it encompasses parses as proper XML. So that's kind of why this helper is called XML, even though it isn't necessarily always used to contain XML. Now, you're likely still skeptical about the usefulness of these helper objects. What point is it to create div objects and p objects and anchor objects? Why not just express those things directly as text in the views? Well, that's what we normally do. But sometimes, say, in the course of our model modules or our controllers, we want to programmatically put together some HTML. And when we do that, it makes a lot of sense to have these helper objects, rather than having to ourselves parse and concatenate a bunch of strings, which is both bothersome to do and error prone. So just generally, when you're in the mode of Python, you don't want to have to dip into some other language, some other syntax, like HTML. You want to work directly in Python syntax, in Python semantics. Another justification for these HTML helpers is that, in some cases, like with form, these helper objects provide some extra intelligent behavior. Form is the best example of this. So consider this here, where we're creating a form, and we're giving the form two inputs. The first input has the attribute type with the value text, and the name with the value myText. And then the second input has just a single attribute, type submit. When we then get the HTML string from this form object using the XML method, this is what we get. We have a form with two input tags, and the inputs have the attributes we specified. But notice that the form is automatically given certain default attributes, such as ngtype as an encode type with the value multi-part slash form data, which specifies how the form data gets encoded when the form is posted. Now, of course, I can change these default attributes if I like, but these, at least, are sensible defaults. So far, this isn't much added extra convenience. But form objects also have a method called accepts. To the accepts method, we first pass the vars, that is the get parameters and the post parameters of the request, and we pass the session object. And optionally, we specify with the named argument form name a name for this form. And the first important thing, which the accepts method does, is to insert two hidden input tags, the first one named underscore form key, and the other one named underscore form name. The form name attribute, you can see, is given the value of whatever we pass to form name, which in this case is Teresa. But if we don't specify any form name, the value here would just be default. The purpose of the form name is to uniquely identify the form within the page. So in cases where you have more than one form, you're going to want to specify a form name. Otherwise, you'll get a name collision because multiple forms will have the same name default. And Web2Py won't be able to distinguish between them. The other added input form key is given a randomly generated value. And this value is different each time the form is generated. So in one request, it's going to be a different value than in any other request. And this generated value is preserved in the session such that when the form is then submitted and sent back to the same page, Web2Py can check and see if the form is a double submission if this is just a repeat of the same form being submitted, which happens sometimes in some browsers because you click the submit button and then you cancel, and then you click submit again, and that ends up posting the same form twice, which could be bad because it might screw up the logic of your application. Now, the reason the method is called accepts is because aside from generating these two hidden inputs, it also checks the request for us to see if the values for this form are being submitted in the current request. Because usually we design our forms to submit back to the same page. So the first time a user goes to a page with a form on it, the form is blank, they fill in the information, they hit submit, and then the data is sent to the same URL as they were already on. So the accepts method checks the request for us to see if this is the form being submitted or if it's just the first time the form is being created and given to the user. If the accepts method determines that the form data is being submitted, and that this is not a double submission, which it determines by checking the form key value in the session, then the accepts method will return true. Otherwise, it will return false. So a very common idiom in Web2Py is when we have a page with a form, first in the action we create the form using our form helper, and then we call on that form the accepts method, passing to the request for us in the session and optionally a name. And if that accepts method returns true, then form data has been submitted, and we process that submitted form data. If accepts returns false, however, then there's no data to process. And notice in the action, we're going to return a dictionary with the form included, because we want to pass the form object, because in the view we're going to render the form with response.write, which reminds me of another important point about the HTML helpers and the XML helper. And that is that when you pass them as argument to response.write, instead of a string, the write method will get their content as text data using the XML method, and the named argument escape, whether it's true or false, has no effect. So remember that the text and HTML helpers is always escaped, and in the XML helper, it's never escaped. So if you pass an HTML helper to response.write, then effectively it's always escaped. And if you pass an XML helper to response.write, then it's never escaped. One more important convenience is the function URL, which returns a URL in the form of the string. And despite the fact that the name is in all caps, don't think that this is really a helper. It's not a class. It's just a function that returns a string. The way URL works when you pass to it three string arguments is that the first is the name of the application, the second is the controller, and the third is the action. And that returns the URL you expect pointing to that action in that controller in that application. If we provide just two string arguments, then this is interpreted as, first, the controller and the action, and the application is inferred from whatever the application of the current request is. And likewise, if we just provide one argument, this is interpreted as just the action. And so both the application and the controller are inferred from whatever the current application and controller are for the current request. Now, optionally, you can also include args and vars. And args are supplied in the form of a list because args have a concept of order. But vars are provided as a dictionary because vars don't have any order, and they come as key value pairs. Now, by default, URL will return a relative URL, a URL which only works from the context of whatever page we're currently generated in the current request. If you want to force URL to return an absolute URL, which is occasionally useful, you specify the optional named argument host with the value true. I guess it's called host because we're explicitly including the host in the output URL. Now, the question is, why do you need to use this URL function rather than just write out URLs yourself? Well, generally speaking, you're going to want to use the URL function as much as possible because it will spare you from having all your links break in your application if you ever apply or modify the URL rewriting rules for your application, which is a feature we'll talk about in the supplement. Normally, Web2Py will return a response with the status code 200 and the message OK, which is the normal kind of successful HTTP response. If, however, in the course of processing a request, an exception gets raised, and that exception doesn't get handled, Web2Py will then send a response with an error page and an error status code. Now, if an error gets raised, which your code doesn't anticipate, well, that's a bug. If, however, you wish to send a response, which is something other than a status 200 code, you can do so by raising an exception type provided by Web2Py called HTTP, all in caps. The HTTP exception constructor expects two main arguments. First, the code itself expressed as an integer. And secondly, some string, which will serve as the body of the response. And optionally, you can include named arguments, which will become additional headers in the response. So the first example here will return a response with the status code 401, which is an error code, and the message in the body will be the string don't go there. And then the second example, it's a 303, which is a kind of redirect. And the body says, go here instead. And we're including a location header with the value HTTP colon slash slash yahoo.com. Because for a redirect, you want to include that header, so the browser knows where it's supposed to redirect to. Understand that the usual behavior of web browsers when they receive a redirect code like 303 is to actually then go to the specified URL. So raising this HTTP exception with status code 303 and header specifying a location of yahoo.com, well, that should redirect the browser to yahoo.com. Because code 303 is the status code that you want to return most often, aside from 200, of course, web2pi provides a more succinct function to do the same thing. So here, this last example, we invoke redirect and pass in just a URL, but that's equivalent to the line above, where we raised HTTP with the status code of 303. The only difference for redirect is that we don't specify any response body. Because, well, with a redirect, the response body doesn't really matter anyway. The user's not going to see it. They're going to be redirected to some other page. Now, the last thing to understand about this HTTP exception is that, unlike other exceptions that get thrown and trigger an error page to be sent back as a response, this HTTP exception will not cause any open database connections to roll back. So if you have any open database connections, when you raise an HTTP exception, the transactions for those connections will commit rather than roll back. So if you do want them to roll back, you should actually do that explicitly before raising this HTTP exception.