pythonflaskflask-admin

Flask-Admin is there a way to append a column to the column_list rather than list them all out?


If I have a model with dozens of fields and all I want to do is add a computed property to the list view, having to spell-out all of the otherwise automatically generated columns from the model and then add the one I want to append by manually specifying everything in a whitelist via column_list...is there a way to make column_list do it's normal default behavior and just append a column to the list?

So say I have a SQLAlchemy model like so...

class Location(Base):
    __tablename__ = "locations"

    id: Mapped[int] = mapped_column(Sequence("location_id_seq", start=1, cycle=True), primary_key=True)
    name: Mapped[str]
    loc_tracking: Mapped[str] = mapped_column(default='Tagged')
    loc_type: Mapped[str] = mapped_column(default='FIFO')
    status: Mapped[str] = mapped_column(default='UnLocked')
    allocatable: Mapped[bool] = mapped_column(default=True)
    capacity: Mapped[int] = mapped_column(default=1)
    #need to put current volume here...yeah it's denormalized but will be used by putaway algs all the time
    #and it'll be too expensive to make it do the SQL every time. You'll also need to make sure add/remove inv
    #from core.inventory deals with updating this value.
    put_sequence: Mapped[int] = mapped_column(default=0)
    pick_sequence: Mapped[int] = mapped_column(default=0)
    stage_in_location_id: Mapped[int] = mapped_column(ForeignKey("locations.id"), nullable=True)
    stage_out_location_id: Mapped[int] = mapped_column(ForeignKey("locations.id"), nullable=True)

    zone_id: Mapped[int] = mapped_column(ForeignKey("zones.id"))

    zone: Mapped["Zone"] = relationship(back_populates="locations")

    @property
    def site_name(self) -> str:
        return self.zone.site_name

If I make a custom ModelView class, I don't want to have to manually list out all of those columns. I'd like to be able to do something like:

class LocationView(ModelView):
    additional_columns = ('site_name',)
    exclude_columns = ('capacity',)

And have it do its normal model introspection and add 'site_name' to the list columns.

I can't seem to figure out what method I need to override to accomplish this. It'd be nice to do something similar for form columns.


Solution

  • You can define column_list as a property and use the fact that the method scaffold_list_columns() returns all the columns except the id column. Note, scaffold_list_columns() is called if column_list is not defined in the view.

    For example:

    class LocationView(ModelView):
        @property
        def column_list(self):
            return self.scaffold_list_columns() + ['site_name']
    
        exclude_columns = ('capacity',)