2009-03-18 5 views
3

Le défi, affiche une sélection de radio dans <ul></ul> imbriqué, regroupés par tâche fk.Django Forms, ModelChoiceField utilisant le widget RadioSelect, regroupés par FK

ie.

class Category(models.Model): 
    # ... 

class Task(models.Model): 
    # ... 
    category = models.ForeignKey(Category) 
    # ... 

forms.py

class ActivityForm(forms.ModelForm): 
    # ... 
    task = forms.ModelChoiceField(
     queryset = Task.objects.all(), 
     widget  = RadioSelectGroupedByFK 
    ) 

widgets.py

class RadioFieldRendererGroupedByFK(RadioFieldRenderer): 
    """ 
    An object used by RadioSelect to enable customization of radio widgets. 
    """ 
    #def __init__(self, attrs=None): 
     # Need a radio select for each?? Just an Idea. 
     #widgets = (RadioSelect(attrs=attrs), RadioSelect(attrs=attrs)) 
     #super(RadioFieldRendererGroupedByFK, self).__init__(widgets, attrs) 

    def render(self): 
     """Outputs nested <ul> for this set of radio fields.""" 
     return mark_safe(
      #### Somehow the crux of the work happens here? but how to get the 
      #### right context?? 
      u'<ul>\n%s\n</ul>' % u'\n'.join(
       [u'<li>%s</li>' % force_unicode(w) for w in self] 
      ) 
     ) 

class RadioSelectGroupedByFK(forms.RadioSelect): 
    renderer = RadioFieldRendererGroupedByFK 

meilleur merci !!

Répondre

1

itertools.groupby() est parfait pour cela. Je suppose que Task et Category ont chacun un attribut name que vous voulez trier par. Je ne connais pas les API Django, donc vous voudrez probablement déplacer le tri dans la requête db, et vous aurez besoin de regarder les attributs du widget pour comprendre comment accéder aux objets de la tâche, mais voici la formule de base:

from itertools import groupby 

# sort first since groupby only groups adjacent items 
tasks.sort(key=lambda task: (task.category.name, task.name)) 

for category, category_tasks in groupby(tasks, key=lambda task: task.category): 
    print '%s:' % category.name 
    for task in category_tasks: 
    print '* %s' % task.name 

Cela devrait imprimer une liste comme:

Breakfast foods: 
* eggs 
* spam 
Dinner foods: 
* spam 
* spam 
* spam 

HTH

Questions connexes