Отправка объекта request.user в ModelForm из общего представления на основе класса в Django

Итак, моя цель - иметь возможность фильтровать набор запросов ModelChoiceField в моей ModelForm, чтобы включать только места, созданные request.user.

Моя ModelForm просто:

class PlaceEventForm(models.ModelForm):
    class Meta:
        model = Event

Я хотел бы иметь возможность добавить что-то вроде:

def __init__(self, *args, **kwargs):
    super(PlaceEventForm, self).__init__(*args, **kwargs)
    self.fields['place'].queryset = Place.objects.filter(created_by=request.user)

Однако я не могу найти способ получить доступ к запросу в ModelForm.

Мой взгляд такой:

class PlaceEventFormView(CreateView):
    form_class = PlaceEventForm
    template_name = 'events/event_create.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(PlaceEventFormView, self).dispatch(*args, **kwargs)

Я не уверен, что это даже близко к тому, что я должен делать, но я попытался:

def get_form_kwargs(self):
    kwargs = super(PlaceEventFormView, self).get_form_kwargs()
    kwargs.update({'place_user': self.request.user})
    return kwargs

Но я получил ошибку: init() получил неожиданный ключевой аргумент 'place_user'

Любые идеи по этому поводу? Или кто-нибудь может придумать способ отфильтровать мой ModelChoiceField в представлении без необходимости передавать мой запрос в ModelForm?


person Brian    schedule 27.04.2011    source источник


Ответы (3)


Вам нужно извлечь ключ user из kwargs в методе PlaceEventForm.__init__(), чтобы он не перешел к методу ModelForm.__init__():

просмотров.py:

class PlaceEventFormView(CreateView):
    form_class = PlaceEventForm
    template_name = 'events/event_create.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(PlaceEventFormView, self).dispatch(*args, **kwargs)

    def get_form_kwargs(self):
        kwargs = super(PlaceEventFormView, self).get_form_kwargs()
        kwargs.update({'place_user': self.request.user})
        return kwargs

формы.py:

class PlaceEventForm(models.ModelForm):
    class Meta:
        model = Event

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('place_user')
        # now kwargs doesn't contain 'place_user', so we can safely pass it to the base class method
        super(PlaceEventForm, self).__init__(*args, **kwargs)
        self.fields['place'].queryset = Place.objects.filter(created_by=user)
person Ivan Virabyan    schedule 27.04.2011
comment
Большое спасибо! Работает отлично. - person Brian; 27.04.2011
comment
Проблемы с пониманием того, как вы это делаете. - person Alex Stewart; 21.07.2013
comment
Я завершил пример, дайте мне знать, если он все еще неясен - person Ivan Virabyan; 22.07.2013
comment
Комментарий # now kwargs doesn't ... после kwargs.pop('place_user') - это первый раз, когда я вижу объяснение в бесчисленных ответах Django Python SO! СПАСИБО! Супер полезно! - person Jheasly; 08.09.2016
comment
Мне потребовалось слишком много времени, чтобы соединить этот ответ с этим ответом, чтобы выяснить, как выбрать внешний ключ с использованием аутентифицированного Пользователь. Использование .initial звуков теперь так просто (рука/лицо) - person Matthew Weber; 28.04.2018

Я на iPhone, но сделайте это:

def get_form(self, form_class):
     form = super(MyView, self).get_form(form_class)
     form.fields['place'].querset = Place....
     return form

Вау это было тяжело! Нет поддержки отступов!

person Yuji 'Tomita' Tomita    schedule 27.04.2011

Чтобы обновить ответ Юджи для Django 1.10+ (включая Django 2.0+), см. пример ниже (обратите внимание на обновленную сигнатуру метода). Предложенный Юдзи подход сохраняет набор запросов в представлении вместе с другой бизнес-логикой и помогает поддерживать чистоту и простоту любого класса формы, расширяющего models.ModelForm.

def get_form(self, form_class=None):
    if form_class is None:
        form_class = self.get_form_class()
    form = super(MyView, self).get_form()
    form.fields['place'].queryset = Place.objects.filter(created_by=self.request.user)
    return form

Короче:

def get_form(self, form_class=None):
    form = super(MyView, self).get_form(form_class)
    form.fields['place'].queryset = Place.objects.filter(created_by=self.request.user)
    return form
person firxworx    schedule 03.03.2018