You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Flask-admin面板调用模型的__init__方法?为何通过面板添加集合时图片压缩逻辑未执行?

Hey there, let's break down your Flask-admin issues step by step:

1. How to make Flask-admin call your model's __init__ method?

Flask-admin's ModelView doesn't use your model's custom __init__ method by default when creating instances via the admin panel. Instead, it directly constructs the SQLAlchemy object and sets attributes using setattr, completely bypassing your __init__ logic.

You have two reliable approaches to fix this:

Approach 1: Override create_model in your ModelView

Redefine how new instances are created in the CollectionsView class to explicitly call your model's __init__:

class CollectionsView(ModelView):
    form_columns = ['name', 'preview_photo']

    def create_model(self, form):
        # Extract data from the form that matches your __init__ parameters
        name = form.name.data
        preview_photo = form.preview_photo.data
        # Create instance using your custom __init__ method
        model = Collections(name, preview_photo)
        # Add to database session and commit
        self.session.add(model)
        self.session.commit()
        return model

This forces the admin panel to use your model's constructor, including the collections_resize call.

Approach 2: Use SQLAlchemy event listeners (more robust)

Instead of relying on __init__ (which can be bypassed by ORM operations), use SQLAlchemy's before_insert and before_update events to run your resize logic. This ensures the code runs whenever a Collection is created or updated—no matter if it's from the admin panel, Python console, or other parts of your app:

from sqlalchemy import event

class Collections(db.Model):
    __tablename__ = 'collections'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    preview_photo = db.Column(db.String, nullable=False)

    def __init__(self, name, preview_photo):
        self.name = name
        self.preview_photo = collections_resize(preview_photo)

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

# Trigger resize before inserting a new Collection
@event.listens_for(Collections, 'before_insert')
def before_insert_collection(mapper, connection, target):
    target.preview_photo = collections_resize(target.preview_photo)

# Optional: Trigger resize when updating the preview photo
@event.listens_for(Collections, 'before_update')
def before_update_collection(mapper, connection, target):
    # Check if the preview_photo field was modified
    state = db.inspect(target)
    if state.attrs.preview_photo.history.has_changes():
        target.preview_photo = collections_resize(target.preview_photo)

This is the better long-term solution because it decouples your image resizing logic from instance creation, making it more reliable across your application.

2. Why isn't collections_resize() running in Flask-admin, but works in the console?

The core issue is how instances are created:

  • When you add a Collection in the Python console, you explicitly call Collections(name, preview_photo), which triggers your __init__ method and runs collections_resize.
  • In the Flask-admin panel, the framework creates instances differently under the hood:
    model = Collections()
    model.name = form.name.data
    model.preview_photo = form.preview_photo.data
    # Then adds to session and commits
    

It skips your custom __init__ entirely, so collections_resize never gets executed. The solutions above (either overriding create_model or using SQLAlchemy events) will resolve this.

Bonus: Handle file uploads properly

If preview_photo is a file upload field, make sure you've configured Flask-admin to handle file uploads first. Update your CollectionsView to use FileUploadField:

from flask_admin.form import FileUploadField
import os

class CollectionsView(ModelView):
    form_extra_fields = {
        'preview_photo': FileUploadField(
            'Preview Photo',
            base_path=os.path.join(app.root_path, 'static/uploads'),
            allowed_extensions=['jpg', 'png', 'jpeg']
        )
    }
    form_columns = ['name', 'preview_photo']

    # If using Approach 1, adjust create_model to handle the uploaded file
    def create_model(self, form):
        name = form.name.data
        uploaded_file = form.preview_photo.data
        # Pass the file object/path to your resize function
        resized_photo_path = collections_resize(uploaded_file)
        model = Collections(name, resized_photo_path)
        self.session.add(model)
        self.session.commit()
        return model

Ensure your collections_resize function can handle the file object that Flask-admin passes (not just a filename string).


内容的提问来源于stack exchange,提问作者nnekkitt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 22:57:33