How to make cascade select boxes in FormAlchemy?

196 views Asked by At

I don't know how to make cascade select boxes in FormAlchemy. Like a address choose form, we have four classes:

class Country(Base, DBBase):
    __tablename__ = 'countries'

    id = Column(Integer, primary_key = True)
    name = Column(String)

    def __init__(self, name):
        self.name = name


class Province(Base, DBBase):
    __tablename__ = 'provinces'

    id = Column(Integer, primary_key = True)
    country_id = Column(Integer, ForeignKey('countries.id'), nullable = True)
    country = relationship('Country', backref = 'provinces')
    name = Column(String)

    def __init__(self, country, name):
        self.country = country
        self.name = name


class City(Base, DBBase):
    __tablename__ = 'cities'

    id = Column(Integer, primary_key = True)
    province_id = Column(Integer, ForeignKey('provinces.id'), nullable = True)
    province = relationship('Province', backref = 'cities')
    name = Column(String)

    def __init__(self, province, name):
        self.province = province
        self.name = name


class District(Base, DBBase):
    __tablename__ = 'districts'

    id = Column(Integer, primary_key = True)
    city_id = Column(Integer, ForeignKey('cities.id'), nullable = True)
    city = relationship('City', backref = 'districts')
    name = Column(String)

    def __init__(self, city, name):
        self.city = city
        self.name = name

When user choose a option from the first level choose box(here's the country field), the second level choose box should list everything belongs to the corresponding first level choose box(If you select US in 'country' field, 'province/state' field should show all states belongs to US). The third level and fourth level boxes are just like this. All data are sorted like the four classes above. And the question is how to make such a form in FormAlchemy?

1

There are 1 answers

2
javex On

I will assume here that you want to build a form that gets dynamically loaded by JavaScript. In its essence you say that the levels two to four are empty until the level above is selected.

It actually depends on the frontend usage here, but I will present a simple solution that will just reload the whole form. You could easily modify this to be more dynamic for a nicer experience.

What you want to do is build a form where you don't know what will be inside those select boxes for which the above level is not yet selected. Let's assume you have a first level where it is a country (for example 'U.S.') and then there's the second level showing you a list of provinces (in this case all states in the US).

Now your user should only see a box for selecting the country first.

Build your form to include all fields (i.e. all levels) but make all but the first empty. Then a user selects the first level. Submit the form, but now because you have the first level, you can build the form with the data for the second level (e.g. get all states in the US from your model). Then pass this to FormAlchemy. Then you send back that form to the user. He selects the second level and you build the list from the model again and pass it to the form. This goes on and on until each level is built.

So your form includes all fields that you have but they are all empty but the first. Each time the form gets submitted you check which levels are present and retreive those from the model. This is the essence of this approach. Implementing this in FormAlchemy is just as easy as building any form at all.

Note: You need to submit the form to the same view again and again and you need to check if the data is complete every time.

I will not give an example here, as the question is aiming for the general approach and not some special FormAlchemy syntax.