Как я могу изменить набор запросов одного из полей в форме, которую я передаю в inlineformset_factory

Я использую дополнительные представления django:

# views.py
from django.forms.models import inlineformset_factory
from extra_views import (CreateWithInlinesView, UpdateWithInlinesView,
                        InlineFormSet, )

class LinkInline(InlineFormSet):
    model = Link
    form = LinkForm
    extra = 1

    def get_form(self):
        return LinkForm({})

    def get_formset(self):
        return inlineformset_factory(self.model, self.get_inline_model(), form=LinkForm, **self.get_factory_kwargs())

class TargetCreateView(BaseSingleClient, CreateWithInlinesView):
    model = Target
    form_class = TargetForm
    inlines = [LinkInline, ]
    template_name = 'clients/target_form.html'

Я хочу, чтобы это поле «ключевые слова» менялось в зависимости от pk, который я передаю в представление через URL-адрес.

# forms.py
class LinkForm(forms.ModelForm):
    keywords = forms.ModelMultipleChoiceField(queryset=ClientKeyword.objects.filter(client__pk=1))

    class Meta:
        model = Link

Однако мне удалось перезаписать init формы:

  1. У меня нет доступа к self.kwargs внутри LinkInline

  2. Даже если бы я это сделал, я не уверен, что смогу передать созданную форму в inlineformset_factory()


person la_f0ka    schedule 24.01.2013    source источник
comment
Поскольку у вас есть pk заранее, не рассматривали ли вы возможность использования curry для передачи pk в форму?   -  person Brandon    schedule 24.01.2013
comment
Я добавил код того, как мне удалось это сделать в ответах, но мне интересно... даже не знаю, что такое карри   -  person la_f0ka    schedule 24.01.2013
comment
Когда мне нужно передать значение в форму, которую я использую в наборе форм, я использую curry: from django.utils.functional import curry MyFormset.form = staticmethod(curry(MyForm, pk=pk)) Форма должна принять kwarg pk в этом пример.   -  person Brandon    schedule 24.01.2013
comment
О,... что-то вроде этого: stackoverflow.com/questions/622982/ . проблема в том, что я могу получить pk только из TargetCreateView. Если бы он был в LinkInline, я мог бы вернуть inlineformset_factory(self.model, self.get_inline_model(), form=curry(LinkForm, pk=pk), **self.get_factory_kwargs()) из get_formset(), но поскольку его там нет, я не знаю, как это будет работать.   -  person la_f0ka    schedule 24.01.2013
comment
Ага. Мне нужно взглянуть на класс представления, чтобы увидеть, где его можно применить.   -  person Brandon    schedule 24.01.2013
comment
К вашему сведению, в Extra Views есть встроенный трюк с каррированием (см. эти строки: github.com/AndrewIngram/django-extra-views/blob/master/), так что проблема просто в том, что представления kwargs не передаются во встроенный, который должен относительно просто ввести. Мне просто нужно убедиться, что нет неприятных проблем с обратной совместимостью. Я также могу передать объект представления, поэтому вам не нужно повторять какую-либо работу, которую вы уже обработали в представлении.   -  person Andrew Ingram    schedule 25.01.2013
comment
Я создал для него задачу здесь: github.com/AndrewIngram/django- дополнительные просмотры/вопросы/35   -  person Andrew Ingram    schedule 25.01.2013


Ответы (1)


Хорошо, если какой-то бедняге нужен ответ на вопрос, как это сделать... Мне удалось сделать это, перезаписав конструктив_inlines() (который является частью extra_views.advanced.ModelFormWithInlinesMixin) и изменив там набор запросов поля.

class TargetCreateView(BaseSingleClient, CreateWithInlinesView):
    model = Target
    form_class = TargetForm
    inlines = [LinkInline, ]
    template_name = 'clients/target_form.html'

    def construct_inlines(self):
        '''I need to overwrite this method in order to change
        the queryset for the "keywords" field'''
        inline_formsets = super(TargetCreateView, self).construct_inlines()
        inline_formsets[0].forms[0].fields[
                'keywords'].queryset = ClientKeyword.objects.filter(
                        client__pk=self.kwargs['pk'])
        return inline_formsets

    def forms_valid(self, form, inlines):
        context_data = self.get_context_data()
        # We need the client instance
        client = context_data['client_obj']
        # And the cleaned_data from the form
        data = form.cleaned_data
        self.object = self.model(
                client=client,
                budget=data['budget'],
                month=data['month']
        )
        self.object.save()
        for formset in inlines:
            f_cd = formset.cleaned_data[0]
            print self.object.pk
            link = Link(client=client,
                    target=self.object,
                    link_type=f_cd['link_type'],
                    month=self.object.month,
                    status='PEN',
            )
            # save the object so we can add the M2M fields
            link.save()
            for kw in f_cd['keywords'].all():
                link.keywords.add(kw)
        return HttpResponseRedirect(self.get_success_url())
person la_f0ka    schedule 24.01.2013