Найти - Пользователи
Полная версия: Динамическое создание поля в ModelForm
Начало » Django » Динамическое создание поля в ModelForm
1 2
Lolka
У меня есть форма (ModelForm), которая используется несколько раз, потому описана в отдельном файле, например такая

class TestForm(forms.ModelForm):
manager = forms.ModelChoiceField(queryset=Manager.objects.filter(city=...))
...
class Meta:
...
Надо в каждом случае передавать в фильтр определенное значение, например, id города или сам City в queryset=City.objects.filter()
Каким образом это сделать?)
Пробовал в __init__'е добавлять поля, но, видимо, я чего то не понимаю в корне :(
Ferroman
Объясни на задаче/примере работы, а то я ничего не понял. Цель какая?
Lolka
Есть форма добавления продукта на склад. В форме продукта есть поле менеджер, а менеджеры бывают разных городов. В момент заполнения формы город, по которому нужно отфильтровать список менеджеров известен и надо его передать в filter() queryset'а менеджера.
Сама форма описана в отдельном файле, т.е., скажем, через request нельзя передать в форму город для фильтра.
Ferroman
AJAX автодополнение с ‘related_fields’ как раз то что Вам нужно. Работает отлично, и легко использовать.
Lolka
Ммммм… Спасибо. Использую, но в других формах :) Но не совсем то.
Я неправильно сказал. Не в момент заполнения, а в момент создания формы, т.е. form = TestForm() уже известен город. Было бы классно так: form = TestForm(city=City.objects.get(…)), потом этот city попадает в __init__ (тот, который будет от TestForm), который модифицирует queryset, или добавляет поле динамически. Вот здесь то и затык, не знаю, как такое сделать. Наверное, так не бывает :)
Ferroman
Хе. Field.initial не поможет случайно :)?
Александр Кошелев
Ferroman
Было бы классно так: form = TestForm(city=City.objects.get(…)), потом этот city попадает в __init__ (тот, который будет от TestForm), который модифицирует queryset, или добавляет поле динамически.
Так так и сделайте.
Ferroman
Хе. Field.initial не поможет случайно smile?
Нет.
smal
А такий варіант не пробували :
class TestForm(forms.ModelForm):

def __init__(self, city=None, *args, **kwargs):
self.city = city
super(self, TestForm).__init__(*args, **kwargs)
if self.city:
self.fields['manager'] = forms.ModelChoiceField(queryset = Manager.objects.filter(city=self.city))
else:
self.fields['manager'] = forms.ModelChoiceField(queryset = Manager.objects.all())
… і у views використовувати як :
...
testform = TestForm(City.objects.get(pk = some_city_id))
Lolka
Да, громандное спасибо, smal, Daevaorn. Теперь получилось. Не догадался использовать словарь self.fields, создавал поля непосредственно, отчего они уже не работали.
Но, пришлось несколько изменить код, т.к. ModelForm принимает еще разное, как то request.POST при отправке формы.
Таким образом (в меру своего понимания процесса, может и наворотил лишнего):
class TestForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
# city придет в kwargs при первой инициализации и надо будет его вытащить,
# в противном случае ModelForm'овский __init__ ругнется на неизвестный аргумент
if 'city' in kwargs:
self.city = kwargs.pop('city')
else:
# один раз инициализированному полю уже не понадобится city, так что все будет хорошо и после request.POST
# даже в таком случае
self.city = None
super(TestForm, self).__init__(*args, **kwargs)
if self.city:
self.fields['manager'] = forms.ModelChoiceField(queryset = Manager.objects.filter(city=self.city))
else:
self.fields['manager'] = forms.ModelChoiceField(queryset = Manager.objects.all())


# views.py
def smth(request):
form = None
if "POST" == request.method:
# это случай с отправленной формой, здесь уже не нужен city, поле уже инициализировано с нужным фильтром
form = TestForm(request.POST)
# а если формы нет, создаем и передаем ей нужный City
if form is None:
form = TestForm(city=City.objects.get(pk = some_city_id))
return render_to_response...
Ferroman
Ясно, я так и не понял вопрос.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB