Search code examples
pythonflasksqlalchemyflask-sqlalchemyflask-admin

flask-admin: How to display meaningful foreign key info in edit and create forms?


I have a Flask-Admin interface to a flask app using SQLAlechemy, and I can't seem to figure out how to handle foreign keys. Specifically, I have the following two models:

class DoctorType(db.Model):
    __tablename__ = 'doctor_type'
    id = db.Column(db.Integer, primary_key=True)
    doctor_type_english_name = db.Column(db.Unicode(255))
    doctors = db.relationship('Doctor')

    def __unicode__(self):
        return self.doctor_type_english_name

class Doctor(db.Model):
    __tablename__ = 'doctor'
    id = db.Column(db.Integer, primary_key=True)
    doctor_english_name = db.Column(db.Unicode(255))
    doctor_type_id = db.Column(db.Integer, db.ForeignKey('doctor_type.id'))

    def __unicode__(self):
        return self.doctor_english_name

I'd like for the doctor_type_id field in the create or edit forms of flask-admin to be a dropdown list of doctor_type_english_name rather than just being an integer input like this:

Doctor Type Input Field

I have __unicode__ functions on the models (I'm using python 2.7). I tried tinkering with form_ajax_refs in my custom form views but with no success. Any help would be much appreciated!


Solution

  • It turns out what I was missing was a relationship from the Doctor class to the DoctorType class. I implemented this with a backref in the DoctorType.doctors relationship:

    class DoctorType(db.Model):
        __tablename__ = 'doctor_type'
        id = db.Column(db.Integer, primary_key=True)
        doctor_type_english_name = db.Column(db.Unicode(255))
        doctors = db.relationship('Doctor', backref='doctor_type')
    
        def __unicode__(self):
            return self.doctor_type_english_name
    

    Once I added that, the "Doctor" edit and create forms in flask-admin had a new field called Doctor Type that was a dropdown of the DoctorType.doctor_type_english_name values, and the Doctor Type ID field was gone by default. This is the behavior I was wanting.