实例参数不能以嵌套的内联形式传递 [英] Instance parameter not being passed in nested inlines form

查看:210
本文介绍了实例参数不能以嵌套的内联形式传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用我的3层模型来实现嵌套内联,目前正在使用它。但是,即使我传递正确的实例,我也不能限制我的相关指示器下拉选项。目前 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):

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)
pre>

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%} 
{相关指标中的表单的%%@
{{formset.as_table}}
{%endfor%}
{%endif%}
/ pre>

更新
我的感觉是我需要将form实例从form.nested传递给BaseIndicatorValueFormSet。但是似乎没有起作用。



屏幕截图提供清晰度。





relatedindicator提供一个下拉列表





当有indicator_value时,选择正确的相关指示符。但是,添加新的indicator_value时,所有相关信息的所有相关指示符都可用。我想限制相关指标的选择到相关的情况(疾病实例)



更新2:我必须定义一个实例 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. Currently relevantindicator displays all values in the table in the drop-down selection. I'd like to limit the values to only those associated with the disease 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 under def __init__. I also needed to define the forms in forms.py since BaseIndicatorFormSet calls IndicatorValueFormSet. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆