views:

140

answers:

1

Application: This is a workshop proposal system for a conference. A user can create presenters and workshops, and link them together. Each user should only have access to the presenters and workshops that s/he created/owns.

# Models:

class Workshop(models.Model):
    name = models.CharField(max_length=140, db_index=True)
    presenters = models.ManyToManyField("Presenter", through="WorkshopPresenter")
    owner = models.ForeignKey(User)

class Presenter(models.Model):
    name = models.CharField(max_length=140, db_index=True)
    owner = models.ForeignKey(User)

class WorkshopPresenter(models.Model):
    workshop = models.ForeignKey("Workshop")
    presenter = models.ForeignKey("Presenter")
    cardinality = models.IntegerField()

To link presenters to workshops, the user is directed to a workshop-specific page, containing a modelformset for WorkshopPresenter. Workshop and cardinality are set by the view after the formset is filled out, so the user only sees a list of dropdowns with possible presenter names. Image of the association page

Question: How can I make it so the presenter dropdowns on this association page only contain presenters who are owned by the current user? The dropdowns should only contain the results of Presenter.objects.filter(owner__exact=request.user). Currently they contain all presenters.

# View snippet that creates the formset:

workshop = Workshop.objects.filter(owner__exact=request.user).get(id=workshop_id)

MyWorkshopPresenterFormSet = modelformset_factory(WorkshopPresenter, 
                                                  formset=WorkshopPresenterFormSet, 
                                                  extra=5, 
                                                  exclude = ("workshop","cardinality"))
formset = MyWorkshopPresenterFormSet(request.POST or None,
                                     queryset=workshop.workshoppresenter_set.all())

WorkshopPresenterFormSet just extends BaseModelFormSet and does some custom validation, nothing fancy.

I've seen some solutions out there that work for regular forms, but nothing to work with modelformsets.

A: 

You can dynamically change the queryset on a form using functional methods (curry), closures, or callbacks. See all three methods in the first three answers to "passing custom form parameters to formset."

Also see James Bennetts post "So you want a dynamic form" for a nice in-depth discussion of the closure method.

Van Gale
Took me a while to really get this clean, but the James Bennett link is very good. Ended up creating a getWorkshopPresenterForm(request.user) function that dynamically defines and returns a form class specific for that user.
modulatrix