2010-09-05 26 views
82

Dato un modello Django, sto cercando di elencare tutti i suoi campi. Ho visto alcuni esempi di fare ciò usando l'attributo _meta model, ma il carattere di sottolineatura davanti al meta indica che l'attributo _meta è un attributo privato e non dovrebbe essere accessibile direttamente? ... Perché, ad esempio, il layout di _meta potrebbe cambiare in futuro e non essere un'API stabile?Ottieni i campi del modello in Django

È _meta un'eccezione a questa regola? È stabile e pronto per l'uso o è considerato una cattiva pratica accedervi? O c'è una funzione o qualche altro modo per introspezionare i campi di un modello senza usare l'attributo _meta? Di seguito è riportato un elenco di alcuni link che mostrano come eseguire l'operazione utilizzando l'attributo _meta

Qualsiasi consiglio è molto apprezzato.

django object get/set field

http://www.djangofoo.com/80/get-list-model-fields

How to introspect django model fields?

+0

possibile duplicato di [Django: ottenere l'elenco dei campi modello?] (Http: // StackOverflow .com/questions/3106295/django-get-list-of-model-fields) – Anto

risposta

113

_meta è privato, ma è relativamente stabile. Ci sono sforzi per formalizzarlo, documentarlo e rimuovere il carattere di sottolineatura, che potrebbe accadere prima di 1.3 o 1.4. Immagino che sarà fatto uno sforzo per garantire che le cose siano compatibili all'indietro, perché molte persone lo hanno comunque utilizzato.

Se si è particolarmente interessati alla compatibilità, scrivere una funzione che accetta un modello e restituisce i campi. Questo significa che se qualcosa cambia in futuro, devi solo cambiare una funzione.

def get_model_fields(model): 
    return model._meta.fields 

Credo che questo restituirà un elenco di oggetti Field. Per ottenere il valore di ogni campo dall'istanza, utilizzare getattr(instance, field.name).

Aggiornamento: i contributori Django stanno lavorando su un'API per sostituire l'oggetto _Meta come parte di un Google Summer of Code. Vedere:
- https://groups.google.com/forum/#!topic/django-developers/hD4roZq0wyk
- https://code.djangoproject.com/wiki/new_meta_api

+40

Dovresti anche essere consapevole del fatto che se hai bisogno anche dei campi many-to-many devi accedere a 'model._meta. many_to_many'! –

+1

Grazie. Buono a sapersi che anche altre persone usano _meta. Mi piace l'idea di avere una funzione wrapper. Lazerscience, grazie anche a te. Buono a sapersi, c'è un buon metodo per ottenere i campi many_to_many. Joe –

+1

def get_model_fields (self): return self._meta.fields usato per restituire facilmente tutti i campi del modello ... Grazie mille ... – garmoncheg

8

Questo è qualcosa che è fatto da sé Django quando si costruisce una forma da un modello. Sta usando l'attributo _meta, ma come notato da Bernhard, usa sia _meta.fields che _meta.many_to_many. Guardando django.forms.models.fields_for_model, questo è come si potesse fare:

opts = model._meta 
for f in sorted(opts.fields + opts.many_to_many): 
    print '%s: %s' % (f.name, f) 
4

I campi modello contenuti in _meta sono elencati in più posizioni come le liste dei rispettivi oggetti campo. Potrebbe essere più semplice lavorare con loro come dizionario in cui le chiavi sono i nomi dei campi.

A mio parere, questo è il modo più irredundant ed espressivo di raccogliere e organizzare gli oggetti del campo modello:

def get_model_fields(model): 
    fields = {} 
    options = model._meta 
    for field in sorted(options.concrete_fields + options.many_to_many + options.virtual_fields): 
    fields[field.name] = field 
    return fields 

(Vedi This example usage in django.forms.models.fields_for_model.)

+2

Puoi accompagnare il tuo codice con una breve descrizione di ciò che sta facendo. –

+2

----- done .----- – jxqz

58

So che questo post è piuttosto vecchio, ma ho appena curato a dire a nessuno che è alla ricerca per la stessa cosa che v'è un'API pubblica e ufficiale per fare questo: get_fields() e get_field()

Uso:

fields = model._meta.get_fields() 
my_field = model._meta.get_field('my_field') 

https://docs.djangoproject.com/en/1.8/ref/models/meta/

+6

Questa è in realtà la risposta giusta per la versione più recente di Django. – chhantyal

+0

1.10 'get_fields()' https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields – Risadinha

1

Che ne dite di questo.

fields = Model._meta.fields 
+1

Immagino che si possa voler accedere alle proprietà di un campo Inoltre, come sottolineato nelle risposte precedenti, ci sono 'many_to_many' e' virtual_fields'. – Jocke

+0

@Jocke giusto sei. Potrebbe esserci la necessità di accedere ad un altro attributo.Risposta modificata. – JDE876

2

Ora c'è metodo speciale - get_fields()

>>> from django.contrib.auth.models import User 
    >>> User._meta.get_fields() 

accetta due parametri che possono essere utilizzati per controllare quali campi vengono restituiti:

  • include_parents

    True per impostazione predefinita. Include in modo ricorsivo i campi definiti sulle classi parent. Se impostato su False, get_fields() cercherà solo i campi dichiarati direttamente sul modello corrente. I campi dei modelli che ereditano direttamente da modelli astratti o classi proxy sono considerati locali, non sul genitore.

  • include_hidden

    false per impostazione predefinita. Se impostato su True, get_fields() includerà i campi utilizzati per supportare la funzionalità di altri campi. Sono inoltre previsti tutti i campi che hanno un related_name (come ManyToManyField, o ForeignKey) che iniziano con un “+”

Problemi correlati