I’m having a form for selecting some products. The form contains other information, and on init I want to pass it a number of products to generate checkboxes for.
class ProductsForm(Form):
# ... other fields
def __init__(self, products, *args, **kwargs):
super(AddToCartForm).__init__(*args, **kwargs)
for p in products:
self.fields[f"product-{p.id}"] = BooleanField()
For this I get "AttributeError: ‘ProductsForm’ object has no attribute ‘fields’.
Django’s BaseForm creates the ‘fields’ from the base_fields, so after the initializing the super class it should be available. Why isn’t it?
And how would I go about adding those dynamic fields?
Hello there!
The functionality that you’re describing is available on the django admin, where on the changelist page you can select some rows of a table, and then select an action. I think that’s a good starting point for where you can find a similar example on how to approach this scenario. This example is for the situation where you only need to select a row, but if you need to POST some information and then also select the products, you may want to take a look into formsets.
I would say that creating dynamic fields is indeed possible, but its not the ideal way of approaching this scenario.
Why are you initializing a non-existent parent class (AddToCartForm)? Consider the following approach to your problem.
from django import forms
class ProductsForm(forms.Form):
products = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple()
)
def __init__(self, products, *args, **kwargs):
super().__init__(*args, **kwargs)
# Assuming products is a list of tuples. e.g. [(key, value), (key2, value2)]
self.fields["products"].choices = products
Sorry, forgot the class name in the init when I abstracted the code for the question, it would be with the “ProductForm”. But yes, calling just super() without the form class avoids the error message!