2

我在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/#sharing-the-queryset。它处理 modelformset_factory,但是 inlineformset_factory 是基于先验的,所以我认为同样的事情应该可以工作:

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

但是进入这个页面只会给出一个 TypeError: init () got an unexpected keyword argument 'queryset'。该参考文献中列出了两种方法,但我都遇到了麻烦。

4

2 回答 2

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
于 2011-03-02T10:28:50.873 回答
0

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

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

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

顺便说一句,很想赞扬提出上述解决方案的人,很想留下一个暖心的答复,但名声太小。

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

这将是自定义表单类(在这种情况下,选择一个人作为relative,但仅限于由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))

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

于 2010-11-10T13:43:17.293 回答