• Aucun résultat trouvé

Dual-Format Decorator

Dans le document Pro Django (Page 125-128)

In this modern “Web 2.0” world, Web applications are often expected to make use of advanced techniques, such as TihDpplNamqaop, to communicate with the server in various, interesting ways. Django supports this, but there are no “standard” mechanisms provided. Instead, each application must decide how best to handle these special types of interactions.

These “Web 2.0” applications often need to render the same content for standard browser requests as for these special types of requests, just in different formats, in order to make sure the application works without JavaScript enabled. It also helps to maintain individual URLs that can be bookmarked and retrieved as a whole, while still allowing just the essential content to be pulled up when necessary.

Since views normally return their responses directly, complete with full contents, this type of functionality only seems possible in one of two ways, each requiring a good deal of code duplication:

฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀

third function that each view can call.

฀ ฀ ฀ ฀eb block inside the view that decides how its content should be output.

Ideally, views for this type of situation could be written without caring which output mechanism is expected. Because decorators are a common technique for removing boilerplate and they also have the ability to create or modify outgoing responses, they’re perfectly suited for the task at hand. It’s quite easy to write a decorator that automatically handles the decision of which path to take and creates an appropriate response based on data provided by the view.

The first step is to decide how a view should provide details of the response without creat-ing the response directly. Since most views use templates to render their content and templates can use dictionaries to provide dynamic values within that content, a dictionary seems like a logical choice. Given that Django also comes bundled with a tool for converting simple Python objects—like dictionaries—directly to JavaScript objects, dictionaries become even more attrac-tive as a way to pass data out of a view in a response- independent manner.

The next step is to determine what should be done with a dictionary returned by the view.

Each type of response will have its own way of handling the dictionary, and the decorator should be written to handle as much as possible. Consider the normal case, where the diction-ary will be passed to a template, which is then returned as the response. The decorator must perform these tasks:

1. Retrieve the appropriate template.

2. Call the original view, capturing the return value for later use.

3. Create a Namqaop?kjpatp object with values returned by the view.

4. Render the template using this context.

5. Return an DpplNaolkjoa containing the rendered content.

That’s a good bit of work to be done, but it’s quite simple to manage inside a decorator.

Another key to consider here is the fact that the decorator has to retrieve and render the tem-plate, which means it has to know what template to use. Rather than try to hard- code the template name in the decorator, it’s best to let it take a single argument to pass in the template name when the decorator is applied. Here’s what the code might look like before taking into account the ability to spit out two different types of responses.

bnki`f]jck*qpeho*bqj_pekj]heilknpsn]lo bnki`f]jck*pailh]pa*hk]`aneilknpcap[pailh]pa bnki`f]jck*pailh]pa*_kjpatpeilknpNamqaop?kjpatp

`ab`q]h[bkni]p$pailh]pa[j]ia%6

`ab`a_kn]pkn$reas%6

`absn]llan$namqaop(&]nco(&&gs]nco%6

`]p]9reas$namqaop(&]nco(&&gs]nco%

pailh]pa9cap[pailh]pa$pailh]pa[j]ia%

_kjpatp9Namqaop?kjpatp$namqaop(`]p]%

napqnjpailh]pa*naj`an$_kjpatp%

napqnjsn]lo$reas%$sn]llan%

napqnj`a_kn]pkn

This basic decorator will allow a view to have a template loaded, rendered and returned automatically. Simply provide a template name to the decorator and return a dictionary, and the decorator does the rest. Moving on to the other side of the problem, the decorator needs to be able to return a string that can be read by JavaScript, containing the same content that would otherwise be provided by the template.

Django comes built- in with a copy of oeilhafokj,2 a library designed for converting Python objects into JavaScript Object Notation (JSON),3 so it can be easily consumed by code inside the Web browser. It even has a custom encoder for use with oeilhafokj, designed to encode some of the particular types Django uses. This encoder can be used to transmit the dictionary’s content directly to the browser, bypassing the template entirely. Combining it with namqaop*eo[]f]t$%—covered in Chapter 7—allows the decorator to decide which path to take, completing the equation.

bnki`f]jck*_kna*oane]hevano*fokjeilknp@f]jckFOKJAj_k`an bnki`f]jck*qpeho*bqj_pekj]heilknpsn]lo

bnki`f]jck*pailh]pa*hk]`aneilknpcap[pailh]pa bnki`f]jck*pailh]pa*_kjpatpeilknpNamqaop?kjpatp

`ab`q]h[bkni]p$pailh]pa[j]ia%6

`ab`a_kn]pkn$reas%6

`absn]llan$namqaop(&]nco(&&gs]nco%6

`]p]9reas$namqaop(&]nco(&&gs]nco%

ebnamqaop*eo[]f]t$%6

2. dppl6++lnk`f]jck*_ki+oeilhafokj+

3. dppl6++lnk`f]jck*_ki+fokj+

fokj9oeilhafokj*`qilo$`]p](_ho9@f]jckFOKJAj_k`an%

napqnjDpplNaolkjoa$fokj%

ahoa6

_kjpatp9Namqaop?kjpatp$namqaop%

napqnjnaj`an[pk[naolkjoa$pailh]pa[j]ia(`]p](_kjpatp%

napqnjsn]lo$reas%$sn]llan%

napqnj`a_kn]pkn

Now What?

URLs form the foundation of your site’s architecture, defining how users access the content and services you provide. Django stays out of the way when it comes to designing your URL scheme, so you’re free to build it however you like. Be sure to take the appropriate time and remember that URL configuration is still a form of site design.

Views are the real workhorses of any application, taking user input and turning it into use-ful output. While the whole of Python is available for views to use, Django does provide one very important tool to handle one of the most common user input tasks on the Web: forms.

113

Forms

O

ne of the key ingredients to modern Web applications is interactivity—the ability to accept input from users, which helps shape their experience. That input can be just about anything, from a simple search term to entire user- submitted novels. The key is the ability to process this input and turn it into a meaningful feature that enriches the experience for all the users of the site.

The process begins by sending an HTML form to the Web browser, where a user can fill it in and submit it back to the server. When the data arrives, it must be validated to make sure the user didn’t forget any fields or enter anything inappropriate. If there was anything wrong with the submitted data, it has to be sent back to the user for corrections. Once all the data is known to be valid, the application can finally perform a meaningful task with it.

It’s possible to do all this without a framework, but doing so involves a lot of duplication if multiple forms are involved. Managing forms manually also introduces a high risk of the programmer taking shortcuts in the process. It’s very common to have a form skip essential validations, either from lack of time or a perceived lack of necessity. Many exploited security holes can be attributed directly to this type of negligence.

Django addresses this by providing a framework to manage those finer details. Once a form is defined, Django handles the details of generating HTML, receiving input and vali-dating data. After that, the application can do whatever it likes with the data received. Like everything else in Django, you’re also still able to bypass this form handling and process things manually if necessary.

Dans le document Pro Django (Page 125-128)