I've got form LimitForm with parameter resource
class LimitForm(FlaskForm):
def __init__(self, resource: Resource, *args, **kwargs):
super(LimitForm, self).__init__(*args, **kwargs)
self.period.choices = Period.choices()
I would like to use this form in other form as field through FormField. Like a
class LimitsForm(FlaskForm)
limits = FieldList(FormField(LimitForm))
but this code raises exception TypeError: __init__() missing 1 required positional argument: 'resource'
How can I pass resource to LimitForm from LimitsForm?
Thanks
You may find is easier to perform some additional logic after the normal initialization of the enclosing class, eg implement you own LimitsForm.__init__()
with special logic at the end. Otherwise, you will likely have to subclass FieldList
and FormField
and override their process
methods and life will become complicated for you if all you need to do is a simple extra step for one use case!
For example, I have a case where I want to do something similar to what you request and pass some special kwargs through a FormField
. Flask-WTF does not seem to do this by default. In this case I am using a QuerySelectField
that I want to pass some special filter through to when I call SQLAlchemy.
In my controller, the call to this is like
form = CampaignForm(obj=campaign, studio=campaign.studio)
Here, the studio is part of a special filter and is only known at run time. However, this studio
kwarg does not make it through the nested FormField
.
Because I'd have to extend and rewire core logic in Flask-WTF to pass this kwarg through the FormField and into GatingExtraForm
, my solution to this problem is to do this instead:
class GatingExtraForm(FlaskForm):
class Meta:
# we do not need CSRF in sub-forms
csrf = False
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_query(studio=kwargs.get('studio'))
# when this form is nested in a FormField, the studio kwarg may not be passed to __init__,
# therefore we make this method available for some post-initialization.
def set_query(self, studio=None):
self.gating_campaign.query = db.query(InAppCampaign).filter(InAppCampaign.active)
if studio:
self.gating_campaign.query = self.gating_campaign.query.filter(InAppCampaign.studio == studio)
self.gating_campaign.query = self.gating_campaign.query.order_by(InAppCampaign.name)
gating_campaign = QuerySelectField(
"Gating Campaign",
get_label='name',
allow_blank=False,
validators=[validators.Optional()]
)
# additional fields here....
class CampaignForm(FlaskForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# because there is no naive way to pass kwargs through on FormField init,
# just do some post init special processing
self.gating_extra.form.set_query(studio=kwargs.get('studio'))
# additional fields here....
gating_extra = FormField(GatingExtraForm)
This is a bit of a hack, I'll admit, but sometimes it's a reasonable trade-off for rare use-cases. If it turns out to be a common pattern, then you can go deeper into extending Flask-WTF.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.