2016-03-02 12 views
7

Ho qualche strano comportamento, almeno per me, che mi sta causando alcuni bug nel mio progetto.Perché la proprietà related_model di Django sta restituendo una stringa anziché un'istanza del modello?

Sto usando Django 1.9 e un pacchetto di terze parti Django (django-jet) che fa uso di field.related_model proprietà a Django di amministrazione e, a volte non riesce perché si aspetta field.related_model restituisce un'istanza di modello e per alcuni dei miei modelli sta tornando il nome del modello .

This is the property defined in Django code:

@cached_property 
def related_model(self): 
    # Can't cache this property until all the models are loaded. 
    apps.check_models_ready() 
    return self.remote_field.model 

cose che ho provato:

  • Se related_model di Django è un @property invece un @cached_property funziona e restituisce l'istanza modello.
  • Se chiamo field.remote_field.model anziché field.related_model nella riga che causa il bug funziona e restituisce l'istanza del modello.

Per favore, avete qualche idea? Posso fare il workaround ma mi piacerebbe sapere perché questo comportamento.

Grazie in anticipo!

risposta

2

Penso che il problema qui si presenti perché Jet sta cercando di utilizzare related_model nel metodo RelatedFieldAjaxListFilter.field_choices() e questo potrebbe essere eseguito prima che tutte le app siano state caricate. Se ho capito bene, il valore related_model è inizialmente una stringa, che viene sostituita con un oggetto modello nel corso dell'inizializzazione del modello. Se si tenta di ottenere tale valore prima che tutte le app siano state caricate, è possibile ottenere una stringa o un oggetto, a seconda dell'ordine in cui vengono caricati i modelli. E poiché si tratta di una proprietà memorizzata nella cache, ottenere un valore di stringa in tale fase causerebbe la memorizzazione del valore di stringa. Si veda, ad esempio, il commento in django.db.models.options,

# The mechanism for getting at the related model is slightly odd - 
# ideally, we'd just ask for field.related_model. However, related_model 
# is a cached property, and all the models haven't been loaded yet, so 
# we need to make sure we don't cache a string reference. 

Facendo related_name una proprietà non memorizzata nella cache, si evita questo problema.

Nel codice django.contrib.admin.filters.RelatedFieldListFilter, non usano related_model per ottenere l'oggetto del modello, ma usano invece una funzione di utilità, django.contrib.admin.utils.get_model_from_relation(). Il RelatedFieldAjaxListFilter.field_choices() dovrebbe probabilmente fare qualcosa di simile.