tags:

views:

390

answers:

2

I have a formset which has a field "Teams" which should be limited to the teams the current user belongs to.

def edit_scrapbook(request):
    u=request.user
    ScrapbookAjaxForm = modelformset_factory(Scrapbook, fields=
          ('description','status','team'))
    choices=False
    for t in u.team_set.all():
        if choices:
            choices=choices,(t.id,t.name)
        else:
            choices=choices,(t.id,t.name)
   if request.method == 'POST':
        formset = ScrapbookAjaxForm(request.POST, 
            queryset=Scrapbook.objects.filter(owner=u))
        if formset.is_valid():
            instances=formset.save(commit=False)
            for i in instances:
                i.owner=request.user
                i.save()
            formset.save_m2m()    
            return HttpResponseRedirect(reverse('scrapbooks.views.index'))
    else:
        formset = ScrapbookAjaxForm(queryset=Scrapbook.objects.filter(owner=u))
        for form in forms:
            for field in form:
                if field.label == 'Team':
                    field.choices=choices
    c=RequestContext(request)
    return render_to_response('scrapbooks/ajax_edit.html', 
             {'fs':formset},context_instance=c)

This does not seem to affect the choices in the form at all. This is quite ugly and probably the result of looking at this problem for way too long. I have also tried using a custom formset but I can't seem to get the custom formset to accept the parameter.

How do I limit the choices for the Team field on my subselect in a formset based on the teams the user is in?

+1  A: 

From django model documentation:

Finally, note that choices can be any iterable object -- not necessarily a list or tuple. This lets you construct choices dynamically. But if you find yourself hacking choices to be dynamic, you're probably better off using a proper database table with a ForeignKey. choices is meant for static data that doesn't change much, if ever.

I would use then the same idea: in the form, you use a ForeignKey for the team and then, you can limit that list with some query.

Some further suggestion:

  • Use a ForeignKey for the team
  • Define your own ModelChoiceField, with a query that will limit its content, basing on a parameter given in its initialization.
  • Override the default field type, to use your own ModelChoiceField. Note that you should pass the filter for the team in the initialization of your ModelChoiceField.
Roberto Liffredo
How do I send the list of iterable objects to the formset? This is where I'm having trouble, I can't seem to get any settings I make in the view to stick in the formset.
Dennis Baker
Ok, I've added a possible way to set the list of iterables.
Roberto Liffredo
A: 

Not sure if this is the cause of the issue, but there's a big problem with the way you build up the choices tuple.

After four teams, choices will look like this:

((((False, (1, u'Team 1')), (2L, u'Team 2')), (3, u'Team 3')), (4, u'Team 4'))

which obviously isn't valid for setting a choice field. A much better way of doing it would be to use a list comprehension in place of the whole loop:

choices = [(t.id,t.name) for t in u.team_set.all()]
Daniel Roseman
Thanks! I'm not used to working with lists in Python yet, that's a much cleaner method and as you say generates the correct result. Unfortunately does not solve my issue.
Dennis Baker