How to filter a django form's multiple choice or foreign key set with a generic view
On: April 14, 2012 By: Travis Millward In: Django , Python , Web Development
On an app I am working on I needed to relate a photo to a project.
I created a model called Connection. It basically has two fields. "Photo" and "Project". They are both foreign keys back to the Photo and Project models.
Well I ran into a problem. I wanted to be able to say okay associate photo A with project B. I could do that and it would show a form with a drop down list of projects to associate a photo with. Problem was it was showing ALL users Projects.
I needed a way to filter the list of Projects in that list to ONLY the logged in user's project's.
Also, I was currently using a generic view (CreateView) and since it was such a simple task wanted to keep using a generic view.
This is what I did on the view.
class AddPhotoToProject(CreateView):
"""
a view where a user can associate a photo with a project
"""
model = Connection
form_class = CreateConnectionForm
def get_context_data(self, **kwargs):
context = super(AddPhotoToProject, self).get_context_data(**kwargs)
context['photo'] = self.kwargs['pk']
context['form'].fields['project'].queryset = Project.objects.for_user(self.request.user)
return context
def form_valid(self, form):
pobj = Photo.objects.get(pk=self.kwargs['pk'])
obj = form.save(commit=False)
obj.photo = pobj
obj.save()
return_json = {'success': True}
if self.request.is_ajax():
final_response = json.dumps(return_json)
return HttpResponse(final_response)
else:
messages.success(self.request, 'photo was added to project!')
return HttpResponseRedirect(reverse('MyPhotos'))
The most important part is the
context['form'].fields['project'].queryset = Project.objects.for_user(self.request.user)
I used a manager to return only projects that hadn't been disabled and in that manager if defined 'for_user' that takes an argument (the user) and filters the list of projects.
Here is that Model Manager
class ProjectManager(models.Manager):
def get_query_set(self):
default_queryset = super(ProjectManager, self).get_query_set()
return default_queryset.filter(disabled=None).order_by('-created_time')
def for_user(self, user):
return super(ProjectManager, self).get_query_set().filter(owner=user)
Posted in: Django , Python , Web Development