在实例化inlineformset时指定queryset

时间:2010-11-10 03:15:22

标签: django django-views django-forms inline-formset

我在views.py中有以下内容来生成一个页面,该页面显示用户“资格”的内联表单集

from django.db.models import User
from models import UserQualification

def edit_quals(request):
    QualsFormSet = inlineformset_factory(User, UserQualification, fields=('qualification', 'qualification_year', 'qualification_source'))
    if request.method == 'POST':
        formset = QualsFormSet(request.POST, request.FILES, instance = request.user)
        if formset.is_valid():
            formset.save()

            #send user somewhere
            return HttpResponseRedirect(request.user.get_profile_url())
    else:
        formset = QualsFormSet(instance = request.user)

    return render_to_response("edit_quals.html", {
        "formset": formset,
    }, context_instance=RequestContext(request))

这很好用,但是,我想创建一个formset只包含某些'UserQualification'对象(即只有那些标记为某种类型的对象),所以当用户访问此页面时仅编辑其资格的子集。这个参考似乎是我想要的:http://docs.djangoproject.com/en/1.1/topics/forms/modelforms/#changing-the-queryset。它处理的是modelformset_factory,但是inlineformset_factory是基于先前的,所以我认为同样的事情应该有效:

formset = QualsFormSet(instance = request.user, queryset=UserQualification.objects.filter(type__startswith='xyz'))

但是转到此页面只会产生一个TypeError: init ()得到一个意外的关键字参数'queryset'。该引用列出了两种方法,我遇到了两种方法。

2 个答案:

答案 0 :(得分:2)

我在这里提供了一个稍微简单的问题答案: Limit Django's inlineformset_factory to only create new objects

对于你想要做的事情,InlineFormSet类看起来像这样:

class BaseInlineFilteredFormSet(BaseInlineFormSet):
    def get_queryset(self):
        ## See get_queryset method of django.forms.models.BaseModelFormSet
        if not hasattr(self, '_queryset'):
            self._queryset = self.queryset.filter(type__startswith='xyz'))
            if not self._queryset.ordered:
                self._queryset = self._queryset.order_by(self.model._meta.pk.name)                
        return self._queryset

答案 1 :(得分:0)

我相信在这种情况下,您需要在调用inlineformset_factory时使用 form 参数,并使用ad-hoc __init__方法传递自定义表单。 如果你需要它是参数化的,我前段时间在这里找到了救生线

    FormSetName.form = staticmethod(curry(FormName, customparam=chosenparam))

其中,如上所述,FormSetName是使用指向FormName的 form 参数定义的。

顺便说一下,我很乐意向那些提出上述解决方案的人表示赞赏,他会喜欢留下温暖的回复,但声誉太低。

编辑以更好地解释我的解决方案:

这将是自定义的表单类(在这种情况下,选择一个人作为亲戚,但只在一部分人中,由< em> relatives()方法):

class RelativeSelectForm(forms.ModelForm):
class Meta:
    model = Person
    fields = ('relative',)

def __init__(self, *args, **kwargs):
    try:
        profile = kwargs.pop('profile')
    except KeyError:
        super(RelativeSelectForm, self).__init__(*args, **kwargs)
        return
    super(RelativeSelectForm, self).__init__(*args, **kwargs)
    self.fields['relative'].queryset = profile.relatives().order_by('name')

并且可以在 vies.py

中使用它
RelativesFormSet = inlineformset_factory(Person, Person, form=RelativeSelectForm, can_delete=True, extra=1)
RelativesFormSet.form = staticmethod(curry(RelativeSelectForm, profile=request.user.profile))

以便每次实例化一个表单集时,它会自动获取填充了正确对象的配置文件参数,而 relative 选择框的查询集仅显示他有权访问的人至。 希望我让自己更清楚一点:)