Reputation: 96
I have a model called Listing
that has a field called categories
that stores all the different categories. There is also a form with a field called categories
that should show a choice field to the user, where the choices should be the values stored in the Listing.categories
model field. So I tried to loop through it but that is not possible as the choice field values are stored in a dict format.
So how do I get the values from the model field into the choice field?
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
for i in Listing.category:
category_choices = (
(i, Listing.category)
)
class NewListing(forms.Form):
...
category = forms.ChoiceField(choices=category_choices)
Upvotes: 0
Views: 943
Reputation: 1065
You can use a ModelChoiceField
in order to pass a queryset and allow the user to choose between all models in this queryset.
You would then get something like:
category = forms.ModelChoiceField(queryset=Category.objects.all())
Upvotes: 1
Reputation: 8222
The class definition as shown here is executed before the models ar initialized. So, you have to do something dynamic to construct the form class or to patch its choices.
I've just tried this at the console and it seems to work. Define BaseForm
with all the fields that you don't want to fiddle with a run-time:
class BaseForm( forms.Form):
something = forms.WhateverField( args)
...
omitting your dynamic choicefield. At runtime, say in the get_form_class
method of a class-based view, build the form you want using 3-argument type
.
I'm not too clear on what queryset returns the set of categories, so adapt this code
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 }
)
If you had a DB table Categories
containing a pair of values choice_value
and choice_label
then you could obtain choices as
choices = Category.objects.filter( ... # maybe via a ManyToMany relation
).values_list('choice_value', 'choice_label')
Upvotes: 0
Reputation: 2663
If Category
is a model then your condition_choices
should be redundant, why use a model if those options are hardcoded? Instead of just using forms.Form
, you should use a model form forms.ModelForm
. You can then pass your category choices through queryset:
class ListingForm(forms.ModelForm):
self.categories = Category.objects.all()
super(ListingForm, self).__init__(*args, **kwargs)
self.fields['categories'].queryset = self.categories
Upvotes: 0
Reputation: 405
For me I have done it in this way:
Models (choice fields are in your models)
CATEGORYCHOICES=(
(1, 'New'),
(2, 'Refurbished'),
(3, 'Opened'),
(4, 'Used'),
)
class Listing(models.Model):
...
categories = models.IntegerField(choices=CATEGORYCHOICES,default=0)
Then in your forms.py you will need to use "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'}),
}
Does it make sense?
You will obvioulsy need to process that data in your views.py. Let me know if you have a question, I am happy to share the code I have for this.
Upvotes: 0