0

I have a little problem with adding new instances using flask-admin. My model is:

class MenuCategory(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    name_category = db.Column(db.String(20), unique=True)
    slug = db.Column(db.String(255))
    order = db.Column(db.Integer)
    path = db.Column(db.Unicode(128))

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

    def __repr__(self):
        return f'<Category {self.name_category}>'

And also ModelView is:

class MenuCategoryView(ModelView):

    column_labels = dict(name_category='Наименование категории', order='Приоритет', path='Изображение')
    column_editable_list = ('name_category', 'order')
    column_default_sort = 'order'
    form_excluded_columns = ('slug')

When i create new instance in also should add "slug" value. It works fine in terminal with flask shell:

>>> m = MenuCategory(name_category='Something here')
{'name_category': 'Something here', 'slug': 'something-here'}
>>> db.session.add(m)
>>> db.session.commit()

But when i create new instance with flask-admin, it just add a new one without "slug" and NULL value. Can someone tell me what I'm doing wrong?

hungry7
  • 49
  • 1
  • 4
  • I take Liran BG solution to make slug from https://stackoverflow.com/questions/23657483/slug-field-on-flask and now it works Can someone explain the difference? – hungry7 Jan 08 '22 at 11:52
  • One advice, when you edit your question it appears on top again so has much bigger chances of being answered – kosciej16 Jan 08 '22 at 13:09

1 Answers1

0

If we look into flask-admin code, we can see such part while creating model:

    def create_model(self, form):
        try:
            # It calls __new__ of model
            model = self._manager.new_instance()
            # TODO: We need a better way to create model instances and stay compatible with
            # SQLAlchemy __init__() behavior
            # Next two lines fill the special _sa_instance_state of model
            state = instance_state(model)
            self._manager.dispatch.init(state, [], {})

            # populate_obj is probably as simple as model.field1 = form.field1 and so on
            form.populate_obj(model)
            self.session.add(model)
            self._on_model_change(form, model, True)
            self.session.commit()

So init isn't even called which even has TODO annotation (however it was added two years ago so I am pretty sure than one won't be resolved at all).

The difference is when adding an event listener you actually listen for events that happens while interacting with database itself, e.g when specific field is set (so in our case, when form.populate_obj would assign model.name_category = ...) which occurs always unlike calling __init__

kosciej16
  • 6,294
  • 1
  • 18
  • 29