Django inlineformset_factory 与查询集
Django inlineformset_factory with queryset
我需要根据视图传递的对象 ID 过滤表单上的外键 select 选项。
我有以下看法:
@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)
这是我的表格:
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']
这会将所有睾丸(这是睾丸模型的外键)传递给表单。我需要的是查询此外键以仅获取与视图给出的 equipamento_id 相关的睾丸。 Teste 与 Equipamento 存在多对多关系。
如果我这样做:
form1 = inlineformset_factory(Actividade, Resultado, form=ResultadoForm(equipamento_id), exclude=('actividade',), extra=len(testes_list))
并在 ResultadoForm 中定义 init 方法注释,我得到以下错误:
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'
但是如果我将 form1 替换为:
form1 = ResultadoForm(equipamento_id)
我可以过滤与那个相关的睾丸 equipamento_id 但我无法创建内联关系。为什么是这样?如何将 equipamento_id 传递给 inlineformset 以创建查询集?请帮助...
问题来了
return type(form)(class_name, (form,), form_class_attrs)
这是您的表单初始化的地方。传递给表单的 __init__
方法的第一个参数是表单的 class 名称(字符串)。然而你的 __init__
看起来像这样
def __init__(self, equipamento_id, *args, **kwargs):
super (ResultadoForm,self ).__init__(*args,**kwargs)
self.fields['teste'].queryset = Teste.objects.filter(equipamento=equipamento_id)
这里的第一个参数是 equipamento_id
并且已分配 'ResultadoForm' 但您在查询过滤器的下一行中将其用作整数。因此错误。查看 modelform_factory 的源代码,不清楚您实际上是如何通过 inlineformset_factory.
将 equipamento_id
作为参数传递的
你将不得不尝试像
这样的东西
equipamento_id = kwargs.pop('equipamento_id')
但我不确定如何通过 inlineform_set 发送。
我需要根据视图传递的对象 ID 过滤表单上的外键 select 选项。 我有以下看法:
@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)
这是我的表格:
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']
这会将所有睾丸(这是睾丸模型的外键)传递给表单。我需要的是查询此外键以仅获取与视图给出的 equipamento_id 相关的睾丸。 Teste 与 Equipamento 存在多对多关系。 如果我这样做:
form1 = inlineformset_factory(Actividade, Resultado, form=ResultadoForm(equipamento_id), exclude=('actividade',), extra=len(testes_list))
并在 ResultadoForm 中定义 init 方法注释,我得到以下错误:
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'
但是如果我将 form1 替换为:
form1 = ResultadoForm(equipamento_id)
我可以过滤与那个相关的睾丸 equipamento_id 但我无法创建内联关系。为什么是这样?如何将 equipamento_id 传递给 inlineformset 以创建查询集?请帮助...
问题来了
return type(form)(class_name, (form,), form_class_attrs)
这是您的表单初始化的地方。传递给表单的 __init__
方法的第一个参数是表单的 class 名称(字符串)。然而你的 __init__
看起来像这样
def __init__(self, equipamento_id, *args, **kwargs):
super (ResultadoForm,self ).__init__(*args,**kwargs)
self.fields['teste'].queryset = Teste.objects.filter(equipamento=equipamento_id)
这里的第一个参数是 equipamento_id
并且已分配 'ResultadoForm' 但您在查询过滤器的下一行中将其用作整数。因此错误。查看 modelform_factory 的源代码,不清楚您实际上是如何通过 inlineformset_factory.
equipamento_id
作为参数传递的
你将不得不尝试像
这样的东西 equipamento_id = kwargs.pop('equipamento_id')
但我不确定如何通过 inlineform_set 发送。