Search code examples
pythonflaskflask-sqlalchemyflask-admin

Slug field in SQL Alchemy/FlaskAdmin


I am trying to create a slug field in one of my DB models. I am using Flask-SQLAlchemy and Flask-Admin. My Class is defined as:

class Merchant(db.Model):
    __tablename__ = 'merchants'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String())
    ...
    slug = db.Column(db.String())

    def __repr__(self):
        return 'Merchant: {}'.format(self.name)

I have attempted to implement something like this from this question:

    def __init__(self, *args, **kwargs):
        if not 'slug' in kwargs:
            kwargs['slug'] = slugify(kwargs.get('name', ''))
        super().__init__(*args, **kwargs)

However it does not work when I am creating the new Merchant using Flask-Admin.

In trying to determine why, I change the init function to simply print kwargs. When I create a new Merchant in Flask-Admin, it prints {}, however when I do it in the python shell, like Merchant(name ='test'), it prints {'name' : 'test'}.

Does anyone know how I can access the arguments being passed to my class at init from Flask-Admin?


Solution

  • It looks like Flask-Admin is not passing constructor arguments when initialising the new object and your code doesn't have any effect. I haven't checked the source code, but they could be doing something like:

    m = Merchant()
    ...
    m.name = 'foo'
    

    I think your best bet if you want to continue using Flask-Admin would be extending the ModelView and implementing the on_model_change hook:

    class MerchantModelView(BaseModelView):
    
        def on_model_change(self, form, model, is_created):
            if is_created and not model.slug:
                model.slug = slugify(model.name)
    

    You can fine more information in the documentation.