2013-09-03 13 views
7

Sto creando un'app Django con utenti personalizzati. Ho delineato i componenti chiave del mio problema di seguito, il codice mancante è indicato da '...'. Il mio modello utente personalizzata ha una relazione di chiave esterna come segue:Django ModelChoiceField non ha un tasto più

class MyCustomUser(models.AbstractBaseUser, models.PermissionsMixin) 
    ... 
    location = models.ForeignKey(Location) 

class Location(models.Model) 
    name = models.CharField(max_length=50, blank=True, null=True) 

Ho scritto un modulo utente personalizzato che include questo campo come segue:

class MyCustomUserCreationForm(models.ModelForm) 
    ... 
    location = forms.ModelChoiceField(Location.objects.all()) 

Tutto questo sembra funzionare correttamente, tuttavia , non vi è alcun pulsante più a destra del campo di selezione per la posizione. Voglio poter aggiungere una posizione quando creo un utente, allo stesso modo in cui puoi aggiungere sondaggi quando crei delle scelte nello Django tutorial. Secondo to this question, potrei non vedere il plus verde se non ho il permesso di cambiare il modello, ma sono registrato come superutente con tutte le autorizzazioni. Qualche idea su cosa sto facendo male?

risposta

11

È necessario impostare un wrapper RelatedFieldWidgetWrapper nel modulo di modello:

Il RelatedFieldWidgetWrapper (trovato in django.contrib.admin.widgets) viene utilizzato nelle pagine Admin per includere la funzionalità su una chiave esterna controllo per aggiungere un nuovo record correlato. (In inglese: mette il piccolo segno più verde a destra del controllo.)

class MyCustomUserCreationForm(models.ModelForm) 
    ... 
    location = forms.ModelChoiceField(queryset=Location.objects.all()) 

    def __init__(self, *args, **kwargs): 
     super(MyCustomUserCreationForm, self).__init__(*args, **kwargs) 
     rel = ManyToOneRel(self.instance.location.model, 'id') 
     self.fields['location'].widget = RelatedFieldWidgetWrapper(self.fields['location'].widget, rel, self.admin_site) 

ho potuto fare un errore nel codice di esempio, in modo da vedere questi messaggi ed esempi:

+1

Mi hai indicato la direzione giusta, grazie per tutti i collegamenti. Ho usato il tuo codice ma ho dovuto modificarlo un po '. Ho dovuto aggiungere un paio di righe a ModelAdmin per passare il sito di amministrazione al form e definire rel come 'MyCustomUser._meta.get_fields ('location'). Rel' – EmeraldOwl

+2

@EmeraldOwl: Minore typo -' MyCustomUser. _meta.get_field ('location'). rel'. – Shubham

2

Google mi ha segnalato questa pagina durante la ricerca come ottenere un'icona "+" accanto ai campi di un modulo personalizzato con rapporto ForeignKey, così ho pensato che vorrei aggiungere.

Per me, usare django-autocomplete-light ha fatto il trucco molto bene, utilizzando la funzionalità "aggiungi un altro".

+0

Il tuo link è rotto. –

6

ho creato metodo basato sulle risposte di cui sopra:

def add_related_field_wrapper(form, col_name): 
    rel_model = form.Meta.model 
    rel = rel_model._meta.get_field(col_name).rel 
    form.fields[col_name].widget = 
    RelatedFieldWidgetWrapper(form.fields[col_name].widget, rel, 
    admin.site, can_add_related=True, can_change_related=True) 

e quindi chiamando questo metodo dalla mia forma:

class FeatureForm(forms.ModelForm): 
    offer = forms.ModelChoiceField(queryset=Offer.objects.all(), required=False) 
    package = forms.ModelChoiceField(queryset=Package.objects.all(), required=False) 
    def __init__(self, *args, **kwargs): 
     super(FeatureForm, self).__init__(*args, **kwargs) 
     add_related_field_wrapper(self, 'offer') 
     add_related_field_wrapper(self, 'package') 

che funziona bene su Django 1.8.2.

+0

Devo aggiungere 'classe Meta \ n \ tmodel = ModeName \ n \ tfields = ('offerta', 'pacchetto')' – luzik

Problemi correlati