I have database tables with a 'TYPE' column and many other fields. In many cases, certain column values are null based on the value of 'TYPE'.
E.g.
if I have a product table , with TYPE having either 'car' or 'helicopter'. The columns are: 
vertical speed, horizontal speed, and horn amplitude. 
In the case of 'car' types, vertical speed should always be null , and in the case of 'helicopter' , horn amplitude should always be null. 
In flask admin, is there any way to hide the fields from being submitted based on the currently selected TYPE's value? 
It is fine if it is a UI level change (i.e. no backend validation is required for security/consistency purposes).
In my real life scenario, there are over 10 columns with 5+ being null in cases, so it would be very helpful if those fields can be removed in the UI (since it makes the form very long and prone to errors).
I am using flask sqlalchemy as the backend for my flask admin.
Fun question. Here is a working solution. So basically you have product types, and each type has certain valid attributes (e.g. car and honking loudness). You can also have general attributes irregardless of the type, e.g. the name of each product.
On the form_prefill, you check what fields are valid for the product type. Then you throw away the invalid fields from the form, and return the form again. It's actually pretty straightforward. 
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import flask_admin as admin
from flask_admin.contrib import sqla
app = Flask(__name__)
app.secret_key = 'arstt'
db = SQLAlchemy(app)
class Product(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    type = db.Column(db.String)
    name = db.Column(db.String)
    vertical_speed = db.Column(db.Integer)
    rotor_rpm = db.Column(db.Integer)
    honking_loudness = db.Column(db.Integer)
    def __str__(self):
        return "{}".format(self.name)
class ProductView(sqla.ModelView):
    general_product_attributes = ['name']
    product_attributes_per_product_type_dict = {
        'driving': ['honking_loudness'],
        'flying': ['rotor_rpm', 'vertical_speed']
    }
    def on_form_prefill(self, form, id):
        product = self.get_one(id)
        form_attributes = self.general_product_attributes + self.product_attributes_per_product_type_dict[product.type]
        for field in list(form):
            if field.name not in form_attributes:
                delattr(form, field.name)
        return form
db.create_all()
admin = admin.Admin(app, name='Example: SQLAlchemy', template_mode='bootstrap3')
admin.add_view(ProductView(Product, db.session))
helicopter = Product(type='flying', name='helicopter1', vertical_speed=99)
car = Product(type='driving', name='car2', honking_loudness=33)
db.session.add(helicopter)
db.session.add(car)
db.session.commit()
Note that this only works for the edit form, all attribtutes are still being displayed on the create form because it is not certain yet what type an product will be.
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