• Aucun résultat trouvé

A Simple Plugin Architecture

Dans le document Pro Django (Page 58-62)

In reusable applications, it’s usually desirable to have a well- defined core set of features, com-bined with the ability to extend those features through the use of plugins. While this may seem like a tall order that might require extensive plugin architecture libraries, it can be done quite simply and entirely in your own code. After all, a successful, loosely- coupled plugin architec-ture comes down to providing just three things:

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

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

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

the plugins should be registered and accessed

Armed with this simple list of requirements and a healthy understanding of what Python has to offer, a few simple lines of code can combine to fulfill these requirements.

_h]ooLhqcejIkqjp$pula%6

`ab[[ejep[[$_ho(j]ia(^]oao(]ppno%6 ebjkpd]o]ppn$_ho(#lhqcejo#%6

Pdeo^n]j_dkjhuata_qpaosdajlnk_aooejcpdaikqjplkejpepoahb*

Ok(oej_apdeoeo]jaslhqcejpula(jkp]jeilhaiajp]pekj(pdeo _h]ooodkqh`j#p^anaceopana`]o]lhqcej*Ejopa]`(epoapoql]

heopsdanalhqcejo_]j^anaceopana`h]pan*

_ho*lhqcejo9WY ahoa6

Pdeoiqop^a]lhqcejeilhaiajp]pekj(sde_dodkqh`^anaceopana`*

Oeilhu]llaj`ejceppkpdaheopeo]hhpd]p#ojaa`a`pkgaal pn]_gkbeph]pan*

_ho*lhqcejo*]llaj`$_ho%

That’s all it takes to get the whole thing working, keeping track of registered plugins, stor-ing them in a list on the lhqcejo attribute. All that’s left is to work out how to achieve each of the points listed earlier. For the following examples, we’ll create an application for validating the strength of a user’s password.

The first step will be the neutral access point, which I’ll call a mount point, from which each side of the equation can access the other. As mentioned before, this relies on metaclasses, so that’s a good place to start.

_h]ooL]ooskn`R]he`]pkn$k^fa_p%6

Lhqcejoatpaj`ejcpdeo_h]oosehh^aqoa`pkr]he`]pal]ooskn`o*

R]he`lhqcejoiqoplnkre`apdabkhhksejciapdk`*

r]he`]pa$oahb(l]ooskn`%

Na_aerao]l]ooskn`pkpaop(]j`aepdanbejeodaooehajphuknn]eoao]

R]hqaAnnknebpdal]ooskn`s]oejr]he`*Pdaat_alpekji]u^a`eolh]ua`

pkpdaqoan(oki]gaoqnaep]`amq]pahu`ao_ne^aosd]p#osnkjc*

[[iap]_h]oo[[9LhqcejIkqjp

You could add more to this if you want, but what’s here is the only part that’s essential to get the process working properly. When looking to add more to it, just know that individual plugins will subclass it and will thus inherit anything else you define on this class. It’s a handy way of providing additional attributes or helper methods that would be useful for all the plugins to have available. Individual plugins can override them anyway, so nothing would be set in stone.

Also note that the plugin mount point should contain documentation relating to how plugins will be expected to behave. While this isn’t expressly required, it’s a good practice to get into, as doing so will make it easier for others to implement plugins. The system only works if all the registered plugins conform to a specified protocol; make sure it’s specified.

Next, set up your code to access any plugins that were registered, using them in whatever way makes sense for the application. Since the mount point already maintains its own list of known plugins, all it takes is to cycle through the plugins and use whatever attributes or meth-ods are appropriate for the task at hand.

`abeo[r]he`[l]ooskn`$l]ooskn`%6

NapqnjoPnqaebpdal]ooskn`s]obeja(B]hoaebpdanas]o]lnk^hai*

bknlhqcejejL]ooskn`R]he`]pkn*lhqcejo6 pnu6

lhqcej$%*r]he`]pa$l]ooskn`%

at_alpR]hqaAnnkn6 napqnjB]hoa napqnjPnqa

`abcap[l]ooskn`[annkno$l]ooskn`%6

Napqnjo]heopkbiaoo]caoej`e_]pejc]julnk^haiopd]psanabkqj`

sepdpdal]ooskn`*Ebeps]obeja(pdeonapqnjo]jailpuheop*

annkno9WY

bknlhqcejejL]ooskn`R]he`]pkn*lhqcejo6 pnu6

lhqcej$%*r]he`]pa$l]ooskn`%

at_alpR]hqaAnnkn(a6 annkno*]llaj`$opn$a%%

napqnjannkno

These examples are a bit more complicated than most, since they require error handling, but it’s still a very simple process. Simply iterating over the list will provide each of the plugins for use. All that’s left is to build some plugins to provide this validation behavior.

_h]ooIejeiqiHajcpd$L]ooskn`R]he`]pkn%6

`abr]he`]pa$oahb(l]ooskn`%6

N]eoaoR]hqaAnnknebpdal]ooskn`eopkkodknp*

ebhaj$l]ooskn`%826

n]eoaR]hqaAnnkn$#L]ooskn`oiqop^a]pha]op2_d]n]_pano*#%

_h]ooOla_e]h?d]n]_pano$L]ooskn`R]he`]pkn%6

`abr]he`]pa$oahb(l]ooskn`%6

N]eoaoR]hqaAnnknebpdal]ooskn``kaoj#p_kjp]ej]juola_e]h_d]n]_pano*

ebl]ooskn`*eo]hjqi$%6

n]eoaR]hqaAnnkn$#L]ooskn`oiqop_kjp]ejkjaola_e]h_d]n]_pan*#%

Yes, it really is that easy! Here’s how these plugins would look in practice.

:::bknl]ooskn`ej$#l]oo#(#l]ooskn`#(#l<ooskn`#%6

***lnejp$#?da_gejc!n***#!l]ooskn`%(

***ebeo[r]he`[l]ooskn`$l]ooskn`%6

***lnejp#r]he`#

***ahoa6

***lnejpBkn_a]jasheja

***bknannknejcap[l]ooskn`[annkno$l]ooskn`%6

***lnejp#!o#!annkn

***

?da_gejc#l]oo#***

L]ooskn`oiqop^a]pha]op2_d]n]_pano*

L]ooskn`oiqop_kjp]ej]pha]opkjaola_e]h_d]n]_pan*

?da_gejc#l]ooskn`#***

L]ooskn`oiqop_kjp]ej]pha]opkjaola_e]h_d]n]_pan*

?da_gejc#l<ooskn`#***r]he`

Now What?

With a solid understanding of what Python has to offer, you’re ready to dive into some of the ways Django uses these tools for many of its features and how you can apply the same tech-niques in your own code. Forming the foundation of most Django applications, models make use of many of these advanced Python features.

45

Models

D

ata is at the center of most modern Web applications, and Django aims to provide support for a variety of data structures and persistence options. Models are the primary aspect of the traditional MVC model that Django maintains intact. Models are an essential part of any appli-cation that needs to persist data across multiple requests, sessions or even server instances.

Django models are defined as standard Python classes, with a wealth of additional fea-tures added in automatically. Behind the scenes, an object- relational mapper (ORM) allows these classes and their instances access to databases. Without this ORM, developers would be required to deal with the database directly, using Structured Query Language (SQL), the stan-dard way to access content in databases.

The primary goal of SQL is to describe and access the relationships that are stored in a relational database. SQL does not generally provide high- level relationships for applications, so most applications include handwritten SQL for data activities. This is definitely possible, but it tends to lead toward lots of repetition, which in and of itself violates the DRY principle outlined in Chapter 1.

These bits of SQL littered throughout an application’s code quickly become unmanage-able, especially since the programmers who have to manage the code aren’t typically experts in relational databases. That also means that these databases are quite prone to bugs, which are often troublesome to track down and fix.

That still doesn’t factor in the biggest issue of all: security. SQL injection1 attacks are a com-mon way for malicious attackers to access or even modify data they shouldn’t have access to.

This occurs when handwritten SQL doesn’t take appropriate precautions with regard to the values that are passed into the database. The more SQL statements that are written by hand, the more likely they are to be susceptible to this type of attack.

All of these problems are extremely common in Web development, regardless of language, and ORMs are a common way for frameworks to mitigate them. There are other ways to avoid some of these problems, such as SQL injection, but Django’s ORM was written with these concerns in mind and handles much of it behind the scenes. By accessing data using standard Python objects, the amount of SQL is minimized, reducing the opportunity for problems to crop up.

1. dppl6++lnk`f]jck*_ki+omh)ejfa_pekj+

Dans le document Pro Django (Page 58-62)