указать набор запросов при создании экземпляра inlineformset - PullRequest
2 голосов
/ 10 ноября 2010

У меня есть следующее в 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 ]

2 голосов
/ 02 марта 2011

Я дал ответ на несколько более простую версию этой проблемы здесь: Ограничить inlineformset_factory Джанго, чтобы создавать только новые объекты

Для того, что вы пытались сделать, класс 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
0 голосов
/ 10 ноября 2010

Я считаю, что в этом случае вам нужно использовать параметр form при вызове inlineformset_factory и передать его в пользовательскую форму, созданную с помощью специального метода __init__. Если вам нужно, чтобы это было параметрическим, я нашел здесь некоторое время назад спасительную линию

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

где, как объяснено выше, FormSetName был определен с параметром form , указывающим на FormName.

Кстати, хотелось бы отдать должное человеку, предложившему вышеупомянутое решение, хотел бы оставить душераздирающий ответ, но слишком мало репутации.

изменить, чтобы лучше объяснить мое решение:

Это будет пользовательский класс формы (в данном случае, чтобы выбрать человека в качестве родственника , но только среди подгруппы людей, возвращенных родственники () метод):

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

, так что каждый раз, когда вы создаете экземпляр формы, он автоматически получает параметр profile , заполненный нужным объектом, и набор запросов для поля выбора относительно показывает только людей, к которым он имеет доступ. Надеюсь, я немного прояснил:)

...