2012-12-17 22 views
8

Diciamo che ho un oggetto Post che può contenere immagini, video e altri tipi di media. Posso usare un GenericForeignKey per collegarli insieme. Qualcosa di simile:GenericForeignKey e Admin in Django

class Post(models.Model): 
    title = models.CharField(...) 
    text = models.TextField(...) 

class AudioMedia(models.Model): 
    ... 

class VideoMedia(models.Model): 
    ... 

class ImageMedia(models.Model): 
    ... 

class MediaObject(models.Model): 
    post = models.ForeignKey(Post) 
    order = models.IntegerField() 

    content_type_media = models.ForeignKey(
    ContentType, limit_choices_to={ 
     'model__in': (
     'audiomedia', 
     'imagemedia', 
     'videomedia') 
    }) 

    object_id_media = models.PositiveIntegerField() 
    obj = generic.GenericForeignKey('content_type_media', 'object_id_media') 

Ora posso facilmente creare un'interfaccia di amministrazione, come:

class MediaObjectAdminInLine(admin.StackedInline): 
    model = MediaObject 
    ct_field = "content_type_media" 
    ct_fk_field = "object_id_media" 
    extra = 0 

class PostAdmin(admin.ModelAdmin): 
    inlines = [MediaObjectAdminInLine] 

Ora la domanda :) In admin /, posso facilmente creare un nuovo post. Per il post, posso facilmente aggiungere più MediaObject. Nel pannello, ho un menu a discesa per scegliere il tipo (audio, video, ...), ma devo manualmente inserire l'ID dell'oggetto che voglio collegare con Post.

Ho provato varie estensioni, tra cui grappelli. Alcuni forniscono la possibilità di cercare l'ID degli oggetti da collegare qui. Voglio la possibilità di aggiungere oggetti qui, ad esempio, aggiungere un AudioMedia, un VideoMedia, un ImageMedia, a seconda di ciò che seleziono dal menu a discesa.

Qualche suggerimento?

+0

Non l'ho provato, ma un pensiero - non si può avere un modulo di amministrazione, e il modulo sovrascrive la casella di testo predefinita per 'object_id' per essere un' ModelChoiceField'? – karthikr

risposta

4

Avresti bisogno di un bel po 'di lavoro per farlo funzionare.

  • Stai chiedendo all'amministratore di visualizzare in modo dinamico un modello, in base al tipo di modello scelto da un menu a discesa.
  • L'amministratore di Django non lo fa (né ne conosce alcuna estensione).

per fare questo lavoro, dovrete:

  1. Scrivi un gestore di eventi JavaScript personalizzato che cattura l'onchange del modello di selezione a discesa.
  2. Quindi chiama l'amministratore di Django e richiede il modello di modello in linea per quel modello.
  3. Aggiorna la pagina HTML corrente con quel modulo del modello.
  4. Quindi sarà necessario intercettare il metodo save() del modello del modello genitore per capire quale modello figlio è gestito e salvarlo correttamente nel database.
  5. Quindi sarà necessario ordinare come ottenere il modello di modello del genitore per visualizzare correttamente il modello di modello del modello appropriato in base al modello del bambino.

Suono scoraggiante? È.

Ecco un modo più semplice:

solo avere un unico modello "Media". Avrai alcuni campi sul modello che sono validi solo per uno dei tuoi tipi (anche se c'è un sacco di crossover).

Nome di tutti i campi specifici di un singolo tipo di supporto con un prefisso per tale tipo di media, ad esempio image_size', or video_title`.

Collegare un gestore JavaScript a ModelAdmin che mostra e nasconde in modo selettivo i campi in base a un menu a discesa per il tipo di supporto.Qualcosa di simile:

class MediaAdmin(admin.ModelAdmin): 
    class Meta: 
     js = ["js/media-types.js",] 

    // media-type.js 
(function($) { 
    $(document).ready(function(){ 
     $('.module[id^=module] .row').hide(); 
     $('.module[id^=module] .row.module').show(); 
     $('.module[id^=module] .row.module select').each(function(){ 
      if ($(this).val() != '') 
      { 
       var group = $(this).parent().parent().parent().parent(); 
       var field = $(this).parent().parent().parent(); 
       var mtype = $(this).val().toLowerCase(); 
       if (mtype != '') 
       {    
        $('.row', group).not(field).slideUp('fast'); 
        $('.row[class*="'+mtype+'"]', group).slideDown('fast'); 
        $('.row[class*="all"]', group).slideDown('fast'); 
       } 
       else 
       { 
        $('.row', group).not(field).slideUp('fast'); 
       } 
      } 
     }); 
     $('.module[id^=module] .row.module select').change(function(){ 
      var group = $(this).parent().parent().parent().parent(); 
      var field = $(this).parent().parent().parent(); 
      var mtype = $(this).val().toLowerCase(); 
      if (mtype != '') 
      { 
       $('.row', group).not(field).slideUp('fast'); 
       $('.row[class*="'+mtype+'"]', group).slideDown('fast'); 
       $('.row[class*="all"]', group).slideDown('fast'); 
      } 
      else 
      { 
       $('.row', group).not(field).slideUp('fast'); 
      } 
     }); 
    }); 
})(django.jQuery); 
0

Mi rendo conto che questo è piuttosto vecchio, ma questo è ancora il primo risultato durante la ricerca di questo.

django-admin-genericfk fa esattamente quello che ti serve.

0

django-admin-genericfk non funziona con Django 1.9.

Diverso da quello che ho trovato solo il seguente modulo:

https://github.com/lexich/genericrelationview

che sembra ben mantenuto. Sfortunatamente, il suo codice JS non funziona bene con il modo in cui Django CMS imposta jQuery (noConflict jQuery), quindi sembra che non sia un'opzione per me. Ma dovrebbe andar bene se non usato nelle pagine di Django CMS ma nel normale Django Admin.