实例参数不能以嵌套的内联形式传递 [英] Instance parameter not being passed in nested inlines form
问题描述
相关指示器
下拉选项。目前 relatedindicator
显示下拉列表中的所有值。我想将值仅限于与疾病
实例相关联的值。有办法吗? 我正在使用在Django中保存嵌套表单的正确方法和 http://yergler.net/blog/2009/09/27/nested-formsets-with-django/ 作为参考。
型号.py
class Disease(models.Model):
disease = models.CharField(max_length = 255)
类指标(models.Model):
relevantdisease = models.ForeignKey(疾病)
指标= models.CharField(max_length = 255)
class IndicatorValue (models.Model):
relatedindicator = models.ForeignKey(Indicator)
indicator_value = models.CharField(max_length = 50)
forms.py
class BaseIndicatorFormSet(BaseInlineFormSet):
pre>
def __init __(self,* args,** kwargs):
尝试:
instance = kwargs.pop('instance')
除了KeyError:
super(BaseIndicatorFormSet,self).__ init __(* args,** kwargs)
def save_new(self,form,commit = True):
instance = super(BaseIndicatorFormSet,self).save_new(form,commit = commit)
form.instance = instance
嵌套在form.nested中:
nested.instance = instance
在nested.cleaned_data中的cd:
cd [nested.fk.name] = instance
返回实例
...
def add_fields(self,form,index):
super(BaseIndicatorFormSet,self).add_fields(form,索引)
try:
instance = self.get_queryset()[index]
pk_value = instance.pk
除了IndexError:
instance = None
pk_value = hash(form.prefix)
form.nested = [
In dicatorValueFormSet(
disease = instance,
queryset = IndicatorValue.objects.filter(relevantindicator = pk_value),
prefix ='value_%s'%pk_value)]
class BaseIndicatorValueFormSet(BaseModelFormSet):
def __init __(self,disease,* args,** kwargs):
super(BaseIndicatorValueFormSet,self).__ init __(* args,*
self.disease =疾病
def save_new(self,form,commit = True):
instance = form.save(commit = False)
instance.disease = self.disease
如果提交:
instance.save()
返回实例
def save_existing(self,form,instance,commit = True) :
return self.save_new(form,commit)
class IndicatorValueForm(forms.ModelForm):
def __init __(self,* args,** kwargs) :
try:
disease_obj = kwargs.pop('disease')
除了KeyError:
super(IndicatorValueForm,self).__ init __(* args,** kwargs)
return
super(IndicatorValueForm,self).__ init __(* args,** kwargs)
queryset = Indicator.objects.filter(relateddisease = disease_obj)
self.fields ['relatedindicator']。queryset = queryset
disease_obj = get_object_or_404疾病,pk = 2)#hard-wired
CurriedForm = formset_factory(IndicatorValueForm,extra = 3)
CurriedForm.form =静态方法(curry(indicatorValueForm,疾病=疾病_obj))
IndicatorValueFormSet = inlineformset_factory (指标,指标值,formset = BaseIndicatorValueFormSet,form = CurriedForm,extra = 3)
IndicatorFormSet = inlineformset_factory(疾病,指标,formset = BaseIndicatorFormSet,extra = 0)
views.py
disease = get_object_or_404(Disease,pk = disease_id)
如果request.method ==POST:
fo rmset = IndicatorFormSet(request.POST,instance = disease)
如果formset.is_valid():
rooms = formset.save_all()
返回HttpResponseRedirect(reverse('option' ,kwargs = {'disease_id':disease_id}))
else:
formset = IndicatorFormSet(instance = disease)
上下文= {'疾病':疾病, :formset,'hide_breadcrumb':hide_breadcrumb}
return render_to_response('valdrui.html',context,context_instance = RequestContext(request))
template.html
{%if relevantindicator.nested%}
/ pre>
{相关指标中的表单的%%@
{{formset.as_table}}
{%endfor%}
{%endif%}
更新
我的感觉是我需要将form实例从form.nested传递给BaseIndicatorValueFormSet。但是似乎没有起作用。
屏幕截图提供清晰度。
relatedindicator提供一个下拉列表
当有indicator_value时,选择正确的相关指示符。但是,添加新的indicator_value时,所有相关信息的所有相关指示符都可用。我想限制相关指标的选择到相关的情况(疾病实例)
更新2:我必须定义一个
实例$ Base code中的BaseIndicatorFormSet中的c $ c> def __init __
。我还需要在Forms.py中定义表单,因为BaseIndicatorFormSet
调用IndicatorValueFormSet
。该实例当前是硬连线的,只是为了看模板是否会呈现。不幸的是,模板中的表单不呈现,也不会产生任何错误。我不知道为什么,因为没有产生错误。解决方案尝试制作一个自定义ModelForm来过滤您的相关指示符字段:
class IndicatorValueForm(forms.ModelForm):
def __init __(self,* args,**
try:
disease_obj = kwargs.pop('disease')
除了KeyError:
super(IndicatorValueForm,self).__ init __(* args,** kwargs)
return
super(IndicatorValueForm,self).__ init __(* args,** kwargs)
queryset = Indicator.objects.filter(relevantdisease = disease_obj)
self.fields ['相关指令']。queryset = queryset
这将修改Forms init 您想要过滤的疾病对象,将其添加到kwargs。
要使用它,我们需要使用咖喱方法将疾病对象传入表单中:
disease_obj =< your-disease-instance>
CurriedForm = staticmethod(curry(indicatorValueForm,disease = disease_obj))
IndicatorValueFormSet = inlineformset_factory(Indicator,IndicatorValue,formset = BaseIndicatorValueFormSet,form = CurriedForm,extra = 3)
现在您的下拉菜单只能显示疾病过滤的指标。
I am implementing nested inlines with my 3-tiered model and currently having it functional. However, I can't limit my
relevantindicator
drop-down choices even though I am passing the correct instance. Currentlyrelevantindicator
displays all values in the table in the drop-down selection. I'd like to limit the values to only those associated with thedisease
instance. Is there a way to do that?I'm using Correct way to save nested formsets in Django and http://yergler.net/blog/2009/09/27/nested-formsets-with-django/ as references.
models.py
class Disease(models.Model): disease = models.CharField(max_length=255) class Indicator(models.Model): relevantdisease = models.ForeignKey(Disease) indicator = models.CharField(max_length=255) class IndicatorValue(models.Model): relevantindicator = models.ForeignKey(Indicator) indicator_value = models.CharField(max_length=50)
forms.py
class BaseIndicatorFormSet(BaseInlineFormSet): def __init__(self, *args, **kwargs): try: instance = kwargs.pop('instance') except KeyError: super(BaseIndicatorFormSet, self).__init__(*args, **kwargs) def save_new(self, form, commit=True): instance = super(BaseIndicatorFormSet, self).save_new(form, commit=commit) form.instance = instance for nested in form.nested: nested.instance = instance for cd in nested.cleaned_data: cd[nested.fk.name]=instance return instance ... def add_fields(self,form,index): super(BaseIndicatorFormSet, self).add_fields(form, index) try: instance = self.get_queryset()[index] pk_value = instance.pk except IndexError: instance=None pk_value = hash(form.prefix) form.nested = [ IndicatorValueFormSet( disease = instance, queryset = IndicatorValue.objects.filter(relevantindicator = pk_value), prefix = 'value_%s' % pk_value)] class BaseIndicatorValueFormSet(BaseModelFormSet): def __init__(self, disease, *args, **kwargs): super(BaseIndicatorValueFormSet, self).__init__(*args, **kwargs) self.disease = disease def save_new(self, form, commit=True): instance = form.save(commit=False) instance.disease = self.disease if commit: instance.save() return instance def save_existing(self, form, instance, commit=True): return self.save_new(form, commit) class IndicatorValueForm(forms.ModelForm): def __init__(self, *args, **kwargs): try: disease_obj = kwargs.pop('disease') except KeyError: super(IndicatorValueForm, self).__init__(*args, **kwargs) return super(IndicatorValueForm, self).__init__(*args, **kwargs) queryset = Indicator.objects.filter(relevantdisease =disease_obj) self.fields['relevantindicator'].queryset = queryset disease_obj = get_object_or_404(Disease, pk=2) #hard-wired CurriedForm = formset_factory(IndicatorValueForm, extra=3) CurriedForm.form = staticmethod(curry(IndicatorValueForm, disease = disease_obj)) IndicatorValueFormSet = inlineformset_factory(Indicator, IndicatorValue, formset=BaseIndicatorValueFormSet, form = CurriedForm, extra=3) IndicatorFormSet = inlineformset_factory(Disease, Indicator, formset=BaseIndicatorFormSet, extra=0)
views.py
disease = get_object_or_404(Disease, pk=disease_id) if request.method == "POST": formset = IndicatorFormSet(request.POST, instance=disease) if formset.is_valid(): rooms = formset.save_all() return HttpResponseRedirect(reverse('option', kwargs={'disease_id':disease_id})) else: formset = IndicatorFormSet(instance=disease) context = {'disease': disease, 'indicators': formset, 'hide_breadcrumb':hide_breadcrumb} return render_to_response('valdrui.html',context, context_instance=RequestContext(request))
template.html
{% if relevantindicator.nested %} {% for formset in relevantindicator.nested %} {{ formset.as_table }} {% endfor %} {% endif %}
Update My feeling is that I need to pass the disease instance from form.nested down to BaseIndicatorValueFormSet. But it does not seem to be working.
Screenshots to provide clarity.
relevantindicator provides a drop-down
When there is a indicator_value, the correct relevantindicator is selected. However, when adding a new indicator_value, all relevantindicator for all relevantdiseases are available. I'd like to limit the relevantindicator choices to the relevantdiseases (the disease instance)
Update 2: I had to define an
instance
in BaseIndicatorFormSet underdef __init__
. I also needed to define the forms in forms.py sinceBaseIndicatorFormSet
callsIndicatorValueFormSet
. The instance is currently hard-wired, just to see if the template will render. Unfortunately, the form in the template does not render but also does not produce any errors. I can't figure out why since there is no error produced.解决方案Try making a custom ModelForm to filter your relevantindicator field:
class IndicatorValueForm(forms.ModelForm): def __init__(self, *args, **kwargs): try: disease_obj = kwargs.pop('disease') except KeyError: super(IndicatorValueForm, self).__init__(*args, **kwargs) return super(IndicatorValueForm, self).__init__(*args, **kwargs) queryset = Indicator.objects.filter(relevantdisease =disease_obj) self.fields['relevantindictor'].queryset = queryset
This amends the Forms init method with the disease object you wish to filter on, adding it to the kwargs.
To use it, we need to pass in the Disease object into the form with the curry method:
disease_obj = <your-disease-instance> CurriedForm = staticmethod(curry(IndicatorValueForm, disease = disease_obj)) IndicatorValueFormSet = inlineformset_factory(Indicator, IndicatorValue, formset=BaseIndicatorValueFormSet, form = CurriedForm, extra=3)
Now your drop down should only show the indicators filtered by disease.
这篇关于实例参数不能以嵌套的内联形式传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!