Как получить несколько значений из поля модели в поле выбора формы?
У меня есть модель Listing
, в которой есть поле categories
, хранящее все различные категории. Есть также форма с полем categories
, которое должно показывать пользователю поле выбора, где выбор должен быть значениями, хранящимися в поле модели Listing.categories
. Я попытался выполнить цикл, но это невозможно, так как значения поля выбора хранятся в формате dict.
Как мне получить значения из поля модели в поле выбора?
models.py
class Category(models.Model):
name = models.CharField(max_length=50)
class Listing(models.Model):
...
category = models.ForeignKey(Category, on_delete=models.PROTECT, null=True)
forms.py:
from .models import Listing
# example of what I was trying to do
condition_choices = (
(1, 'New'),
(2, 'Refurbished'),
(3, 'Opened'),
(4, 'Used'),
)
###
for i in Listing.category:
category_choices = (
(i, Listing.category)
)
class NewListing(forms.Form):
...
category = forms.ChoiceField(choices=category_choices)
Вы можете использовать поле ModelChoiceField для того, чтобы передать набор запросов и позволить пользователю выбрать между всеми моделями в этом наборе. Тогда вы получите что-то вроде :
category = forms.ModelChoiceField(queryset=Category.objects.all())
Для себя я сделал это следующим образом:
Модели (поля выбора находятся в ваших моделях)
CATEGORYCHOICES=(
(1, 'New'),
(2, 'Refurbished'),
(3, 'Opened'),
(4, 'Used'),
)
class Listing(models.Model):
...
categories = models.IntegerField(choices=CATEGORYCHOICES,default=0)
Затем в файле forms.py вам нужно будет использовать "form select"
class NewListing(ModelForm):
class Meta:
model = Listing
fields = ('field_name1','field_name2')
labels ={
'field_name1': '',
'field_name2': '',
}
widgets = {
'field_name1':forms.Select(attrs={'class':'form-control'}),
'field_name2': forms.Select(attrs={'class':'form-control'}),
}
Имеет ли это смысл?
Вам, очевидно, потребуется обработать эти данные в вашем views.py. Дайте мне знать, если у вас есть вопрос, я буду рад поделиться кодом, который у меня есть для этого.
Если Category
является моделью, то ваша condition_choices
должна быть избыточной, зачем использовать модель, если эти опции жестко закодированы? Вместо того, чтобы просто использовать forms.Form
, вы должны использовать модельную форму forms.ModelForm
. Затем вы можете передать выбор категории через queryset:
class ListingForm(forms.ModelForm):
self.categories = Category.objects.all()
super(ListingForm, self).__init__(*args, **kwargs)
self.fields['categories'].queryset = self.categories
Определение класса, как показано здесь, выполняется до инициализации моделей. Таким образом, вы должны сделать что-то динамическое, чтобы сконструировать класс формы или изменить его варианты.
Я только что попробовал это в консоли, и, кажется, это работает. Определите BaseForm
со всеми полями, с которыми вы не хотите возиться во время выполнения:
class BaseForm( forms.Form):
something = forms.WhateverField( args)
...
отключение динамического поля выбора. Во время выполнения, скажем, в методе get_form_class
представления на основе класса, создайте нужную вам форму с помощью 3-аргумента type
.
Я не очень понимаю, что queryset возвращает набор категорий, поэтому адаптируйте этот код
class SomethingView( FormView):
...
def get_form_class( self):
# interrogate the DB to get a list of categories, or categories and labels.
choices = list( enumerate(categories) ) # [ (0,'cat0'), (1,'cat1'), ...]
choicefield = forms.ChoiceField( choices=choices, ...)
return type('My_runtime_form',
(BaseForm, ),
{ 'category': choicefield }
)
Если бы у вас была таблица DB Categories
, содержащая пару значений choice_value
и choice_label
, то вы могли бы получить варианты как
choices = Category.objects.filter( ... # maybe via a ManyToMany relation
).values_list('choice_value', 'choice_label')