pallets-eco/flask-admin

QuerySelectField ignores changes to data / default in ModelView.create_form

csvance opened this issue · 2 comments

Hi, I am trying to set a QuerySelectField to a the currently logged in user in the create interface. Basically I have a "created_by_user_id" column that I would like to automatically set, the default value is dependent by the currently logged in user.

python==3.10.12
Flask==3.0.3
Flask-Admin==1.6.1
Flask-WTF==1.2.1

This works, the change is reflected in the generated HTML:

class ApplicationModelView(ModelView):
  def create_form(self, obj=None)
    form = super().create_form(obj=obj)
    form.text_field.data = "testing"
    return form

This does not work (no change in generated HTML, 1 is still selected by default)

class ApplicationModelView(ModelView):
  def create_form(self, obj=None)
    form = super().create_form(obj=obj)
    form.select_field.data = 2
    return form

I have tried all kinds of workarounds to no avail:

  • calling form.process() after
  • using form.select_field.process_data(2)
  • using form.select_field.default = 2

To me it looks like something is clearly busted here, I had to resort to handling this with Javascript.

So I finally got it to work, but its ugly. I had to use the User SQLAlchemy instance and override its eq to check if the id fields were equal. The part where it checks if something should be selected does == between the user object populating the form and the one stored in form.select_field.data. That fails because they are different instances. However changing the comparison operator fixes the problem in this case.

class ApplicationModelView(ModelView):
  def create_form(self, obj=None)
    form = super().create_form(obj=obj)
    form.select_field.data = user_obj
    return form

class User(Base):
  def __eq__(self, other):
    return isinstance(other, type(self)) and self.id == other.id

Use this at your own risk, I have no idea if there are unintended consequences.

Are you able to provide a minimal reproduction code snippet for the problem you've flagged in the first post? Would be happy to investigate if this is still an issue; it feels like you shouldn't need to resort to JS or overriding __eq__.