I need to filter foreignkey select options on a form based on an object id passed by a view. I have the following view:
@login_required()
def QAView(request, equipamento_id):
form = ActividadeForm()
equipamento = Equipamento.objects.get(id=equipamento_id)
testes_list = Teste.objects.filter(equipamento=equipamento_id)
form1 = inlineformset_factory(
Actividade, Resultado, form=ResultadoForm,
exclude=('actividade',), extra=len(testes_list))
context = {'equipamento_id': equipamento_id,
'data':datetime.now(), 'equipamento': equipamento,
'form': form, 'testes_list': testes_list,
'form1': form1}
template = 'SFM/Equipamento/QA.html'
return render(request, template, context)
Here are my forms:
class ActividadeForm(forms.ModelForm):
class Meta:
model = Actividade
fields = ['tipo']
exclude = ['conclusoes']
class ResultadoForm(forms.ModelForm):
frequencia = forms.CharField(max_length=50)
tolerancia = forms.CharField(max_length=255)
#def __init__(self, equipamento_id, *args, **kwargs):
#super (ResultadoForm,self ).__init__(*args,**kwargs)
#self.fields['teste'].queryset = Teste.objects.filter(equipamento=equipamento_id)
class Meta:
model = Resultado
exclude = ['actividade']
This passes all the testes (which is a foreignkey to Teste Model) to the form. What I need is to query this foreignkey to get only the testes related to equipamento_id given by the view. Teste has a manytomany relation to Equipamento. If I do:
form1 = inlineformset_factory(Actividade, Resultado, form=ResultadoForm(equipamento_id), exclude=('actividade',), extra=len(testes_list))
and define init method commented in ResultadoForm, I get the following error:
Traceback:
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\core\handlers\base.py" in get_response
149. response = self.process_exception_by_middleware(e, request)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\core\handlers\base.py" in get_response
147. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\contrib\auth\decorators.py" in _wrapped_view
23. return view_func(request, *args, **kwargs)
File "C:\Users\i11931\Documents\DjangoProjects\IPO\SFM\views.py" in QAView
37. exclude=('actividade',), extra=len(testes_list))
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\forms\models.py" in inlineformset_factory
1049. FormSet = modelformset_factory(model, **kwargs)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\forms\models.py" in modelformset_factory
847. error_messages=error_messages, field_classes=field_classes)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\forms\models.py" in modelform_factory
545. return type(form)(class_name, (form,), form_class_attrs)
File "C:\Users\i11931\Documents\DjangoProjects\IPO\SFM\forms.py" in __init__
23. self.fields['teste'].queryset = Teste.objects.filter(equipamento=equipamento_id)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\manager.py" in manager_method
122. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\query.py" in filter
790. return self._filter_or_exclude(False, *args, **kwargs)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\query.py" in _filter_or_exclude
808. clone.query.add_q(Q(*args, **kwargs))
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\sql\query.py" in add_q
1243. clause, _ = self._add_q(q_object, self.used_aliases)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\sql\query.py" in _add_q
1269. allow_joins=allow_joins, split_subq=split_subq,
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\sql\query.py" in build_filter
1199. condition = lookup_class(lhs, value)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\lookups.py" in __init__
19. self.rhs = self.get_prep_lookup()
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\fields\related_lookups.py" in get_prep_lookup
98. self.lookup_name, self.rhs)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\fields\__init__.py" in get_prep_lookup
744. return self.get_prep_value(value)
File "C:\Users\i11931\Programas\Python3.5.1\lib\site-packages\django-1.9-py3.5.egg\django\db\models\fields\__init__.py" in get_prep_value
976. return int(value)
Exception Type: ValueError at /SFM/Equipamento/6/QA/
Exception Value: invalid literal for int() with base 10: 'ResultadoForm'
But if I replace form1 by:
form1 = ResultadoForm(equipamento_id)
I am able to filter the testes related to that equipamento_id but I cannot create the inline relations. Why is this? How can I pass that equipamento_id to the inlineformset in order to make a queryset?? Please Help...
Here's the problem
return type(form)(class_name, (form,), form_class_attrs)
This is where your form is initialized. The first parameter that is passed to the __init__
method of your form is the class name of the form a String. However your __init__
looks like this
def __init__(self, equipamento_id, *args, **kwargs):
super (ResultadoForm,self ).__init__(*args,**kwargs)
self.fields['teste'].queryset = Teste.objects.filter(equipamento=equipamento_id)
The first parameter here is equipamento_id
and that's assigned 'ResultadoForm' but you are using it as an integer in the next line in the query filter. Hence the error. Looking at the source code for modelform_factory it isn't clear how you an actually pass equipamento_id
as a parameter via inlineformset_factory.
you will have to try something like
equipamento_id = kwargs.pop('equipamento_id')
But I am unsure how this can be sent through inlineform_set.