Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding 'scaffold_form' makes 'form_columns' ignored #2545

Open
dhait opened this issue Oct 21, 2024 · 1 comment
Open

Adding 'scaffold_form' makes 'form_columns' ignored #2545

dhait opened this issue Oct 21, 2024 · 1 comment

Comments

@dhait
Copy link

dhait commented Oct 21, 2024

I've added a scaffold_form() function on my view, in order to override the querying of a specific child field. But it is put at the bottom of the form, instead of at the top, as requested by 'form_columns'.

# In the ShareView class -->

    form_widget_args = {
        'company' : { 'disabled': True },
    }

    def scaffold_form(self):
        form_class = super(ShareView, self).scaffold_form()

        # Override the 'company' field to only display the currently assigned company
        form_class.company = QuerySelectField(
            'Company',
            query_factory=lambda: self._get_current_company(),
            allow_blank=False,
            get_label='name'
        )
        return form_class

    def _get_current_company(self):
        # Return a query that only contains the current company (no query for all)
        if self.model.company:
            return Company.query.filter_by(id=self.model.company_id)
        return Company.query.filter_by(id=None)  # Return empty if no company is assigned

    form_columns = ('company', 'stock_exchange','name','code', 'isin', 'status', 'slug', 'remote_id', 'price',
         'in_issue','dividend_cover','stamp_duty_exempt')

I expect that the 'Company' field will be at the top of the 'edit' form (disabled).
Instead, it is at the very bottom after all the other fields.

Environment:

  • Python version: 3.12
  • Flask version: 3.0.3
  • Flask-Admin version: 1.6.1
@samuelhwilliams
Copy link
Contributor

Flask-Admin currently relies on WTForm's ordering when rendering fields.

Flask-Admin adds fields to the form based on form_columns, and generally WTForms respects this, so I suspect this bug is caused by the form being generated and then you "adding" (overriding) the company field, which maybe sends it to the back of the list of fields on the form.

It does look like flask-admin docs say form_columns controls the rendering order of fields, so I think we should fix this.

At a glance this appears to be the likely culprit:

{% for f in form if f.widget.input_type != 'hidden' %}
{% if form_opts %}
{% set kwargs = form_opts.widget_args.get(f.short_name, {}) %}
{% else %}
{% set kwargs = {} %}
{% endif %}
{{ render_field(form, f, kwargs) }}
{% endfor %}

In the mean time, a workaround might be to set form_rules as per https://flask-admin.readthedocs.io/en/latest/api/mod_contrib_sqla/#flask_admin.contrib.sqla.ModelView.form_rules. As form_rules overrides the ordering of fields that comes from wtforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants