Reputation: 6037
In my Form I have a dropdown-list projects
, which should show some elements based on a certain type, using ModelChoiceField
. This query needs some parameter, but how do how can I pass this parameter to the form?
class TaskCreate(CreateView):
model = Task
fields = ['name', 'description', 'project']
def form_valid(self, form):
return super(TaskCreate, self).form_valid(form)
\
class TaskcreateForm(forms.ModelForm):
projects = forms.ModelChoiceField(queryset=Project.objects.filter(type=someParameter))
class Meta:
model = Task
Upvotes: 1
Views: 2822
Reputation: 6005
You should use the get_form_kwargs method of the view:
class TaskCreate(CreateView):
model = Task
fields = ['name', 'description', 'project']
def form_valid(self, form):
return super(TaskCreate, self).form_valid(form)
def get_form_kwargs(self):
"""
Returns the keyword arguments for instantiating the form.
"""
kwargs = super(TaskCreate, self).get_form_kwargs()
kwargs.update({'my_var': 'my value'})
return kwargs
And then capture that parameter in the form __init__ method. You also need to set the queryset for the field in the __init__ method:
class TaskcreateForm(forms.ModelForm):
projects = forms.ModelChoiceField(queryset=Project.objects.none())
def __init__(self, *args, **kwargs):
self.my_var = kwargs.pop('my_var')
super(TaskcreateForm, self).__init__(*args, **kwargs)
self.fields['projects'].queryset = Project.objects.filter(type=self.my_var))
class Meta:
model = Task
You must use kwargs.pop() otherwise the call to super()
will raise an error due to the unexpected keyword argument.
CCBV is a great resource for detailing the methods available on all of the generic class-based views.
Upvotes: 2
Reputation: 45555
You can override the get_form()
method of the view. For example if you provide this parameter via the request.GET
then the view will be like this:
class TaskCreate(CreateView):
...
def get_form(self, form_class):
form = super(TaskCreate, self).get_form(form_class)
form.fields['project'].queryset = Project.objects.filter(
type=self.request.GET['type'])
return form
And in the form you can set the queryset to none()
:
class TaskcreateForm(forms.ModelForm):
projects = forms.ModelChoiceField(queryset=Project.objects.none())
class Meta:
model = Task
Upvotes: 1
Reputation: 22449
Catavaran's answer is straight forward. Another option could be to add the type to the url pattern (untested syntax)
url(r'^create/(?P<type>[-\w]+)/$', TaskCreate.as_view(), name='create_task')
This way you'll receive the type via kwargs, and you'd still be able to create custom links to certain types using a reverse pattern
{% url 'create_task' type='foo' %}
Don't forget there's a chance you'll get bogus input from the GET param.
Upvotes: 0