2012-09-06 1 views
5

Ho un modello di azione che ha una chiave esterna che specifica la frequenza con un'azione ripresenta:Ottenere dati aggiuntivi in ​​Django selezione forma tendina

class Reoccurance(models.Model): 
    label = models.CharField("Label", max_length=50, unique = True) 
    days = models.IntegerField("Days") 

    def __unicode__(self): 
     return self.label 

    class Meta: 
     ordering = ['days'] 

class Action(models.Model): 
    name = models.CharField("Action Name", max_length=200, unique = True) 
    complete = models.BooleanField(default=False, verbose_name="Complete?") 
    reoccurance = models.ForeignKey(Reoccurance, blank=True, null=True, verbose_name="Reoccurance") 

sto facendo un ModelForm d'azione che si traduce in codice HTML per reoccurance (sulla base dei valori del database che esistono per la tavola Reoccurance):

<select id="id_reoccurance" class="select" name="reoccurance"> 
    <option value="" selected="selected">---------</option> 
    <option value="12">2 Days</option> 
    <option value="1">3 Days</option> 
    <option value="2">5 Days</option> 
    <option value="10">6 Days</option> 
    <option value="9">1 Week</option> 
    <option value="3">10 Days</option> 
    <option value="4">2 Weeks</option> 
    <option value="11">3 Weeks</option> 
    <option value="5">1 Month</option> 
    <option value="13">6 Weeks</option> 
    <option value="6">1 Quarter</option> 
    <option value="7">6 Months</option> 
    <option value="8">1 Year</option> 
</select> 

Come si può vedere, anche se le selezioni sono in ordine giorno crescente, i valori sono fuori uso perché sono stati inseriti nella banca dati fuori di ordine.

Desidero creare un jquery che calcoli dinamicamente la data in cui l'azione si ripresenterà. Ci vorrà la data di oggi e aggiungere il numero di giorni che corrispondono alla selezione che l'utente ha scelto. Ma con i dati che ottengo nel modulo, non posso tradurre la selezione in un determinato numero di giorni. Anche se i valori degli elementi di opzione erano in ordine, non indica ancora che "1 anno" è uguale a 365 giorni.

Questi dati si trovano tuttavia nella tabella Reoccurance. Per label = "1 Year", days = 365. Allo stesso modo per tutti gli elementi nella tabella Reoccurance.

C'è un modo per riscrivere il mio modelForm in modo che forse il valore dell'opzione di ogni elemento a discesa sia uguale al numero di giorni per quella selezione? Perché allora, ho potuto accedere al numero di giorni:

$("#id_reoccurance").change(function() { 
    alert($(this).val()); 
}); 

Sarebbe questo influenzare negativamente la mia capacità di legare la selezione reoccurance adeguata alla corretta riga della tabella Reoccurance? C'è un altro modo in cui posso accedere a questo giorno/label tie in jquery sul mio modello di modulo?

Aggiornamento

Grazie al suggerimento di Joseph per controllare this post, sono stato in grado di includere un titolo nel mio elemento opzione:

from django.utils.html import conditional_escape, escape 
from django.utils.encoding import force_unicode 

class SelectWithTitles(forms.Select): 
    def __init__(self, *args, **kwargs): 
     super(SelectWithTitles, self).__init__(*args, **kwargs) 
     # Ensure the titles dict exists 
     self.titles = {} 

    def render_option(self, selected_choices, option_value, option_label): 
     title_html = (option_label in self.titles) and \ 
      u' title="%s" ' % escape(force_unicode(self.titles[option_label])) or '' 
     option_value = force_unicode(option_value) 
     selected_html = (option_value in selected_choices) and u' selected="selected"' or '' 
     return u'<option value="%s"%s%s>%s</option>' % (
      escape(option_value), title_html, selected_html, 
      conditional_escape(force_unicode(option_label))) 

class ChoiceFieldWithTitles(forms.ChoiceField): 
    widget = SelectWithTitles 

    def __init__(self, choices=(), *args, **kwargs): 
     choice_pairs = [(c[0], c[1]) for c in choices] 
     super(ChoiceFieldWithTitles, self).__init__(choices=choice_pairs, *args, **kwargs) 
     self.widget.titles = dict([(c[1], c[2]) for c in choices]) 

class ActionForm(forms.ModelForm): 
    reoccurance = ChoiceFieldWithTitles() 

    def __init__(self, *args, **kwargs): 
     super(ActionForm, self).__init__(*args, **kwargs) 

     choices = [] 
     for pt in Reoccurance.objects.all(): 
      choices.append((pt.id, pt.label, pt.days)) 
     self.fields['reoccurance'] = ChoiceFieldWithTitles(choices = choices) 

Fantastic. Così ora ottengo il seguente nel mio modello:

<select id="id_reoccurance" class="selectwithtitles" name="reoccurance"> 
    <option value="12" title="2" >2 Days</option> 
    <option value="1" title="3" >3 Days</option> 
    <option value="2" title="5" >5 Days</option> 
    <option value="10" title="6" >6 Days</option> 
    <option value="9" title="7" >1 Week</option> 
    <option value="3" title="10" >10 Days</option> 
    <option value="4" title="14" >2 Weeks</option> 
    <option value="11" title="21" >3 Weeks</option> 
    <option value="5" title="30" >1 Month</option> 
    <option value="13" title="42" >6 Weeks</option> 
    <option value="6" title="90" >1 Quarter</option> 
    <option value="7" title="180" >6 Months</option> 
    <option value="8" title="365" >1 Year</option> 
</select> 

Ok, sembra che ci siamo quasi, ma mi sto sgambetto. Nel jquery, sto cercando il seguente per ottenere il titolo dell'opzione selezionata:

$(function() { 
    $("#id_reoccurance").change(function() { 
     alert($(this).attr('title')); 
    }); 
}); 

problema è che sta tornando come indefinito!

Aggiornamento Capito

$(function() { 
    $("#id_reoccurance").change(function() { 
     alert($(this).find("option:selected").attr("title")); 
    }); 
}); 
+0

io credo che si possa inserire i dati nei campi del modulo attributi nel __init __() del modulo, ma non sono sicuro del metodo esatto per farlo poiché non lo metti solo su un singolo widget di input ma su un numero di elementi

risposta

2

Basando off this question/answer (e questo è ruvida, non testato, si spera un inizio):

class myClassForm(forms.Form): 
    class Meta: 
     model = myClass 
     fields=["name"] 

    reoccurrance = forms.ChoiceField(label="Reoccurance", choices=(), 
            widget=forms.Select(attrs={'class':'selector'})) 


def __init__(self, *args, **kwargs): 
    super(myClassForm, self).__init__(*args, **kwargs) 
    choices = [] 
    for pt in Reoccurance.objects.all(): 
     choices.append((pt.id, unicode(pt.days))) 
    self.fields['reoccurrance'].choices = choices 
+0

Stavo pensando sulla stessa linea. Pochi problemi: voglio che il testo di ogni selezione sia "l'etichetta". Così, invece, ho provato choices.append ((unicode (pt.days), pt.label)).Ma questo mi lascia il problema che ho previsto. Il modello si aspetta che il valore della selezione sia uguale all'ID, non ai giorni. Quindi, quando tenta di allineare la selezione dell'utente con l'id nel database, nella migliore delle ipotesi, mostra una discrepanza tra ciò che è stato scelto e ciò che viene restituito. Nel peggiore dei casi, dice che non vi è alcuna voce dalla tabella di Reoccurance che corrisponda alla selezione dell'utente (ad esempio, non esiste un ID uguale a 365). –

+1

Controllare questo? http://stackoverflow.com/questions/5089396/django-form-field-choices-adding-an-attribute – Joseph

+0

Grande! Grazie!! Questo ottiene i giorni nel modello. Ma ora come ottengo i giorni dall'opzione selezionata? Vedi revisione sopra. –