2013-01-22 19 views
8

Desidero aggiungere attributi personalizzati alle istanze di un modello Django. Questi attributi non dovrebbero essere memorizzati nel database. In qualsiasi altra classe, gli attributi sarebbero semplicemente inizializzati con il metodo __init__.Qual è il modo giusto per disporre di attributi di istanza personalizzati nei modelli Django?

Posso già vedere tre modi diversi per farlo, e nessuno di loro è completamente soddisfacente. Mi chiedo se esiste un modo migliore/più pitonico/djangoista per farlo?

  1. Override il metodo __init__: la sintassi è un po 'contorto, ma funziona.

    from django.db.models import Model 
    
    class Foo(Model): 
        def __init__(self, *args, **kwargs): 
        super(Model, self).__init__(*args, **kwargs) 
        self.bar = 1 
    
  2. Utilizzare un post_init segnale di Django: questo richiede codice della classe al di fuori della definizione di classe, che non è molto leggibile.

    from django.dispatch import receiver 
    from django.db.models.signals import post_init 
    @receiver(post_init, sender=Foo) 
        def user_init(sender, instance, *args, **kwargs): 
         instance.bar = 1 
    
  3. Utilizzare un metodo di istanza anziché di un attributo: avente un'eccezione generale sollevato come comportamento predefinito è un po 'fastidiosa.

    class Foo(Model): 
        def bar(self): 
        try: 
         return self.bar 
        except: 
         self.bar = 1 
        return self.bar 
    

Di queste tre scelte, le prime appare come il meno peggio per me. Cosa ne pensi? Qualche alternativa?

risposta

3

Esclusione __init__ è il modo giusto.

7

vorrei utilizzare il decoratore di proprietà disponibili in pitone

class Foo(Model): 
    @property 
    def bar(self): 
     if not hasattr(self, '_bar'): 
      self._bar = 1 

     return self._bar 

Quindi è possibile accedere che, proprio come una proprietà invece di invocare una funzione con()

Si potrebbe anche ottenere un po 'più dritto in avanti con questo avendo il fallback integrato, anziché memorizzato

class Foo(Model): 
    @property 
    def bar(self): 
     return getattr(self, '_bar', 1) 
+0

Interessante, non sapevo del decoratore @property. Ma non pensi che sia terribilmente brutto? –

+0

Non se si desidera avere un valore predefinito predefinito invece di specificare getattr in qualsiasi altro punto del codice. Questo è solo un modo standard per creare metodi accessor in python, quindi se è brutto dovremo solo portarlo a Guido come miglioramento per v3 :-P – Bryan

+1

Sono appena tornato a questa domanda con un paio di anni in più di Python sotto la mia cintura (2013! ero giovane e innocente poi ...). Penso che oggi andrei con la tua risposta. L'approccio '@ property' è piuttosto pitonico. D'altra parte, i costruttori di modelli di django sono raramente superati. –

Problemi correlati