Flask Admin One to One Relationship and Edit Form

Viewed 387

I am building an admin dashboard for my web app using Flask-Admin. For the user/address relationship, I am using a one to one relationship. On the user edit form, I'd like to be able to edit the individual components of the address (i.e. street address, city or zip) similar to what inline_models provides. Instead, flask-admin generates a select field and only allows me to select a different addresses.

I tried using inline_models = ['address'] in the UserModelView definition. However, I got the address object not iterable error due to the user/address relationship being configured to uselist=False. Switching uselist to True would affect other parts of my code, so I'd prefer to leave it as False.

From looking in flask-admin/contrib/sqla/forms, within the function get_forms, its being assigned a one to many tag which is what drives the use of a select field.

Before diving in further, I figured it best to see if anyone else has come across this or has a recommended fix/workaround.

models.py

class User(db.Model):    
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64))

    address = db.relationship("Address", backref="user", 
              cascade="all, delete-orphan", lazy=False,
              uselist=False, passive_deletes=True)

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    line1 = db.Column(db.String(128))
    zip = db.Column(db.String(20), index=True)
    city = db.Column(db.String(64), index=True, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id",
                                              ondelete="CASCADE"))

admin.py

class UserModelView(ModelView):
     column_list = [User.username, 'address']
     form_columns = (User.username, 'address')

admin = Admin(name='Ask', template_mode='bootstrap3')
admin.add_view(UserModelView(User, db.session))
1 Answers

You can create 2 relations

    # Relation for flask admin inline model
    address_cms_relationsip = db.relationship(
        "Address", backref="user", cascade="all, delete-orphan", lazy=False,
        uselist=True, passive_deletes=True)

    address_relationship = db.relationship(
        "Address", cascade="all, delete-orphan", lazy=False,
        uselist=False, passive_deletes=True)

    @property
    def address(self):
        return self.address_relationship

In your code you can use property address

user: User # some User object
user.address.city
Related