I am trying to use Flask-Admin to create a create/edit form for the model Matriline shown below. This model has a string field name and a field pod_id with a foreign key constraint to another model Pod, which itself has a foreign key field to a Clan model.
The default form created by Flask-Admin shows the name field and a select field for the Pod instances, but I would like to add a field Clan, which would reset the Pod list according to the Clan instance selected.
To add the Clan field I override the default ModelView for Matriline and add an extra select field Clan with all the Clan instances, as shown in the view MatrilineView below.
Now I need to add some Ajax code to the rendered form to reset the list of pods every time a new clan is selected.
Do I have to replace entirely the default form by a custom one including the Ajax code? Or is there any easier way to that with Flask-Admin?
<b>models.py</b>
...
class Matriline(db.Model):
__tablename__ = 'matriline'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(64))
pod_id = db.Column(db.Integer, db.ForeignKey('pod.id'))
def __unicode__(self):
return self.name
class Pod(db.Model):
__tablename__ = 'pod'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(64))
matrilines = db.relationship('Matriline', backref='pod', lazy='select')
clan_id = db.Column(db.Integer, db.ForeignKey('clan.id'))
def __unicode__(self):
return self.name
class Clan(db.Model):
__tablename__ = 'clan'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Unicode(64))
pods = db.relationship('Pod', backref='clan', lazy='select')
def __unicode__(self):
return self.name
...
<b>views.py</b>
from flask_admin.contrib import sqla
from wtforms import SelectField
from orcall import models
class MatrilineView(sqla.ModelView):
column_hide_backrefs = False
form_extra_fields = {
'clan': SelectField('Clan',
choices=[ (c.id, c.name) for c in models.Clan.query.all()])
}
column_list = ('name', 'pod', 'clan')
...
# Setup Flask-User user_manager = CustomUserManager(app, db, User) Forms shows a complete list of customizable forms. Notice that in a simple use case like this, the form will work without customizing the accompanying view method.
After you’ve copied the Form template files, you can edit any template file in your app/templates/flask_user/ directory, and change it to your liking. All Flask-User templates extend from app/template/flask_user_layout.html . You can configure all Flask-User templates to extend from your own layout template by:
# Setup Flask-User user_manager = CustomUserManager(app, db, User) View methods perform lots of intricate operations, so use this feature with caution. Be sure to read the source code of the default view method and make sure you understand all that it does before attempting to modify its behavior.
Here’s a nice clean solution to pass those custom attributes, keeping the built-in SelectField, but using a custom widget which supports providing attributes for any of the options via a keyed dictionary. I want to generate markup equivalent to this boostrap 4 example, where the first option is disabled.
You are need to use a QuerySelectField. For example:
from flask.ext.admin.form import Select2Widget
class MatrilineView(sqla.ModelView):
column_hide_backrefs = False
form_extra_fields = {
'clan': sqla.fields.QuerySelectField(
label='Clan',
query_factory=lambda: Clan.query.all(),
widget=Select2Widget()
)
}
column_list = ('name', 'pod', 'clan')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With