2010-10-24 12 views

risposta

3

Due usi comuni di Expandos sono schemi parzialmente fissi e proprietà precedenti deleting.

Uso spesso Expando quando ho un tipo che richiede proprietà leggermente diverse tra le entità; in altre parole, quando ho bisogno di uno schema dinamico "parzialmente". Un caso d'uso è un'applicazione che prende gli ordini in cui alcuni prodotti sono liquidi (pensa acqua), alcuni sono unità fisiche (pensi DVD), e alcuni sono "altro" (pensa la farina). Alcuni campi, come codice articolo, prezzo e quantità, sono sempre necessari. Ma, cosa succede se sono necessari anche i dettagli di come è stata calcolata la quantità?

In genere una soluzione a schema fisso sarebbe quella di aggiungere una proprietà per tutte le variabili che potremmo usare: peso, quota, prima e dopo i pesi del nostro magazzino e così via. Questo fa schifo. Per ogni entità la maggior parte degli altri campi non sono necessari.

class Order(db.Model): 
    # These fields are always needed. 
    item_code = db.StringProperty() 
    unit_of_measure = db.StringProperty() 
    unit_price = db.FloatProperty() 
    quantity = db.FloatProperty() 

    # These fields are used depending on the unit of measure. 
    weight = db.FloatProperty() 
    volume = db.FloatProperty() 
    stock_start_weight = db.FloatProperty() 
    stock_end_weight = db.FloatProperty() 

Con Expando possiamo fare molto meglio. Potremmo usare lo unit_of_measure per dirci come abbiamo calcolato la quantità. Le funzioni che calcolano la quantità possono impostare i campi dinamici e le funzioni che leggono le informazioni di quel metodo sanno cosa cercare. E l'entità non ha un mucchio di proprietà non necessarie.

class Order(db.Expando): 
    # Every instance has these fields. 
    item_code = db.StringProperty() 
    unit_of_measure = db.StringProperty() 
    unit_price = db.FloatProperty() 
    quantity = db.FloatProperty() 


def compute_gallons(entity, kilograms, kg_per_gallon): 
    # Set the fixed fields. 
    entity.unit_of_measure = 'GAL' 
    entity.quantity = kilograms/kg_per_gallon 

    # Set the gallon specific fields: 
    entity.weight = kilograms 
    entity.density = kg_per_gallon 

Si potrebbe ottenere un risultato simile utilizzando una proprietà di testo o blob e la serializzazione di un dict di 'altri' valore ad essa. Expando fondamentalmente 'automatizza' quello per te.

+1

Un'altra opzione nella situazione descritta consiste nell'utilizzare PolyModel, invece. –

+1

È possibile; ma potresti finire per creare e importare tonnellate di modelli per gestire le variazioni (per questo tipo di esempio). Mi occupo di liquidi, e ci sono un * sacco * (la nostra app usa circa 12) di modi per calcolare il volume. –

+0

Una delle più frequenti somme di ragioni per il modello Expando. Grazie! – Jon