• Aucun résultat trouvé

PRESERVING A VIEW’S NAME AND DOCUMENTATION

Dans le document Pro Django (Page 120-123)

฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀ ฀

The first thing to consider when writing a decorator is that it receives all the arguments intended for the view itself. Previous sections covered this, but only in the usual context of using &]nco and &&gs]nco to receive the arguments and pass them straight through to the wrapped function. With views, you know in advance that the first argument will always be the incoming request object, so a wrapper function can anticipate this and receive the request separately from the other arguments.

By interacting with the request object prior to executing the view, decorators can do two important things: make decisions based on the incoming request and make changes to the request to alter how the view operates. These tasks aren’t mutually exclusive and many deco-rators do both, such as the following example from Django.

bnki`f]jck*qpeho*bqj_pekj]heilknpsn]lo

`aboap[paop[_kkgea$reas%6

=qpki]pe_]hhuoapopdapaop_kkgeakj]hh]jkjuikqoqoano(

okpd]ppdau_]j^ahkcca`ejiknaa]oehu(sepdkqpd]rejc pkdep]oal]n]pahkcejl]ca*

`absn]llan$namqaop(&]nco(&&gs]nco%6 ebnamqaop*qoan*eo[]jkjuikqo$%6 namqaop*oaooekj*oap[paop[_kkgea$%

napqnjreas$namqaop(&]nco(&&gs]nco%

napqnjsn]lo$reas%$sn]llan%

PRESERVING A VIEW’S NAME AND DOCUMENTATION

The built- in admin interface generates documentation for your application’s views using the name and docstring of the view function itself. By using decorators to wrap the function, we’re essentially replacing the original view function with the wrapper. This causes the admin interface to see the wrapper instead of the view.

Ordinarily, this would cause the name and docstring of the view to be lost in the shuffle, so the admin’s documentation feature doesn’t work properly with these views. To get the right documentation, those attributes of the function must remain intact throughout the wrapping process.

Django provides an additional decorator, living at `f]jck*qpeho*bqj_pekj]h*sn]lo, which is designed to copy these attributes onto the wrapped function so it looks more like the original view. This process is described in more detail in Chapter 9, but all the examples in this section use it to illustrate best practices for decorating views.

Another common use of decorators is to extract some common code from the beginning or end of a set of views. This can be especially useful when looking at incoming arguments, as decorators can perform any lookups and initializations prior to calling the view. Then, decora-tors can simply pass fully prepared objects to the view, rather than raw strings captured from a URL.

bnki`f]jck*qpeho*bqj_pekj]heilknpsn]lo bnki`f]jck*odknp_qpoeilknpcap[k^fa_p[kn[0,0 bnkijaso*ik`ahoeilknp=npe_ha

`abcap[]npe_ha[bnki[e`$reas%6

Napnearao]ola_ebe_]npe_ha(l]ooejceppkpdareas`ena_phu

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

]npe_ha9cap[k^fa_p[kn[0,0$=npe_ha(e`9ejp$e`%%

napqnjreas$namqaop(]npe_ha9]npe_ha(&]nco(&&gs]nco%

napqnjsn]lo$reas%$sn]llan%

The great thing about a decorator like this is that, even though the logic it contains is fairly minimal, it does cut down on the amount of code that has to be duplicated for views that all get an =npe_ha object according to an ID provided in the URL. This not only makes the views themselves a bit more readable, but any time you can cut down on code that has to be written, you can help reduce bugs.

Also, by having access to the response, decorators can make some interesting decisions about how that response should behave. Middleware classes, described in Chapter 7, have much more use for accessing the response, but there are still useful things decorators can do.

Of note is the ability to set the content- type of the response, which can control how the browser deals with the content once it receives it. Chapter 7 describes this in more detail and also how it can be set when creating the response. However, it’s also possible to set it after the response has already been created and returned from a view.

This technique can be a good way to override the content- type for specific types of views.

After all, if no content- type is specified, Django pulls a value from the @AB=QHP[?KJPAJP[PULA setting, which defaults to #patp+dpih#. For certain types of views, especially those intended for Web services, it may be better to serve them using another content- type, such as #]llhe_]pekj+

tih#, while still being able to use generic views.

bnki`f]jck*qpeho*bqj_pekj]heilknpsn]lo

`ab_kjpajp[pula$_[pula%6

Kranne`aopda?kjpajp)Pulalnkre`a`^updareas*

=__alpo]oejcha]ncqiajp(pdajas?kjpajp)Pula r]hqapk^asneppajpkpdakqpckejcnaolkjoa*

`ab`a_kn]pkn$reas%6

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

naolkjoaW#?kjpajp)Pula#Y9_[pula napqnjsn]lo$reas%$sn]llan%

napqnj`a_kn]pkn

A lesser- used feature of view decorators is the ability to catch any exceptions that are raised by the view or any code it executes. Views typically just return a response directly, but

there are still many situations where a view may opt to raise an exception instead. One com-mon example, found in many of Django’s own generic views, is raising the Dppl0,0 exception to indicate that an object couldn’t be found.

Chapter 9 covers the exceptions Django provides in its standard distribution, many of which can be raised by views for one reason or another. In addition, many of the standard Python exceptions could be raised for various situations, and it can be useful to catch any of these. A decorator can perform a variety of additional tasks when an exception is raised, from simply logging the exception to the database to returning a different type of response in the case of certain exceptions.

Consider a custom logging application with a log entry model like this:

bnki`]papeiaeilknp`]papeia bnki`f]jck*`^eilkpik`aho _h]ooAjpnu$ik`aho*Ik`ah%6

l]pd9ik`aho*?d]nBeah`$i]t[hajcpd9.11%

pula9ik`aho*?d]nBeah`$i]t[hajcpd9.11(`^[ej`at9Pnqa%

`]pa9ik`aho*@]paPeiaBeah`$`ab]qhp9`]papeia*jks(`^[ej`at9Pnqa%

`ao_nelpekj9ik`aho*PatpBeah`$%

The application providing this model could also provide a decorator for projects to apply to their own views that logs exceptions to this model automatically.

bnki`f]jck*qpeho*bqj_pekj]heilknpsn]lo bnkiiuhkc]ll*ik`ahoeilknpAjpnu

`abhkcca`$reas%6

Hkco]juannknopd]pk__qnna``qnejcpdareas ej]ola_e]hik`ah`aoecjbkn]ll)ola_ebe_annkno

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

napqnjreas$namqaop(&]nco(&&gs]nco%

at_alpAt_alpekj(a6

Hkcpdaajpnuqoejcpda]llhe_]pekj#oAjpnuik`ah

Ajpnu*k^fa_po*_na]pa$l]pd9namqaop*l]pd(#Reasat_alpekj#(opn$a%%

Na)n]eoaepokop]j`]n`annknd]j`hejcopehh]llheao n]eoa

napqnjsn]lo$reas%$sn]llan%

The recurring theme with all these examples is that view decorators can encapsulate some common code that would otherwise have to be duplicated in every instance of the view. In essence, view decorators are a way to extend the view’s code before or after the original code.

It’s important to generalize these examples in order to realize just how much is possible with view decorators. Any boilerplate you find yourself duplicating at the beginning or end of your views is fair game to be placed in a decorator to save some time, energy and trouble.

Dans le document Pro Django (Page 120-123)