Flask SqlAlchemy AttributeError: 'str' object has no attribute '_sa_instance_state'

Flask SqlAlchemy AttributeError: 'str' object has no attribute '_sa_instance_state'

因此,我尝试添加我保存在指定目录中的图像名称,但此错误不断出现并且数据库中没有添加任何内容,尽管图像一直保存在指定目录中。 这是我所有的文件 Models.py

from shop import db
from datetime import datetime


class Product(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), nullable=False)
    price = db.Column(db.Numeric(10,2), nullable=False)
    stock = db.Column(db.Integer, nullable=False)
    desc = db.Column(db.Text, nullable=False)
    pub_date = db.Column(db.DateTime, nullable=False,
        default=datetime.utcnow)

    brand_id = db.Column(db.Integer, db.ForeignKey('brand.id'),
        nullable=False)
    brand = db.relationship('Brand',
        backref=db.backref('brands', lazy=True))

    category_id = db.Column(db.Integer, db.ForeignKey('category.id'),
        nullable=False)
    category = db.relationship('Category',
        backref=db.backref('categories', lazy=True))

    image_1 = db.Column(db.String(256), nullable=False, default='image1.jpg')
    image_2 = db.Column(db.String(256), nullable=False, default='image2.jpg')
    image_3 = db.Column(db.String(256), nullable=False, default='image3.jpg')

    def __repr__(self):
        return '<Product %r>' % self.name

class Brand(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False, unique=True)

class Category(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False, unique=True)

db.create_all()

forms.py

from flask_wtf.file import FileAllowed, FileField, FileRequired
from wtforms import Form,StringField, IntegerField, BooleanField, TextAreaField, validators

class AddProducts(Form):
    name = StringField("Name", [validators.DataRequired()])
    price = IntegerField("Price:RS ", [validators.DataRequired()])
    stock = IntegerField("Stock", [validators.DataRequired()])
    desc = TextAreaField("Description", [validators.DataRequired()])
    # colors = TextAreaField("Colors", [validators.DataRequired()])

    image_1 = FileField('Image 1', [FileRequired(), FileAllowed(['jpg, jpeg, png, svg, gif']), "Images Only please"])
    image_2 = FileField('Image 2', [FileRequired(), FileAllowed(['jpg, jpeg, png, svg, gif']), "Images Only please"])
    image_3 = FileField('Image 3', [FileRequired(), FileAllowed(['jpg, jpeg, png, svg, gif']), "Images Only please"]) 

*routes.py


@app.route('/addproduct', methods=["GET", "POST"])
def addproduct():
    brands = Brand.query.all()
    categories = Category.query.all()
    form = AddProducts(request.form)
    if request.method == "POST":
        name = form.name.data
        price = form.price.data
        stock = form.stock.data
        desc = form.desc.data
        brand = request.form.get('brand')
        category = request.form.get('category')
        image_1 = photos.save(request.files['image_1'] , name=secrets.token_hex(10) + '.')
        image_2 = photos.save(request.files['image_2'] , name=secrets.token_hex(10) + '.')
        image_3 = photos.save(request.files['image_3'] , name=secrets.token_hex(10) + '.')
        print(f"Image 1 name:{image_1}, its type:{type(image_1)}")
        product = Product(name=name, price=price, stock=stock, desc=desc, brand=brand, category=category, 
                                image_1=image_1,image_2=image_2, image_3=image_3)
        db.session.add(product)
        flash(f"{name} has been added to database.", 'success')
        db.session.commit()
        return redirect(url_for('admin'))
    return render_template('products/addproduct.html', title='Add Product', form=form, brands=brands, 
                            categories=categories)

所有图像类型都是字符串,模型字段也是字符串,但我仍然不断收到此错误。 这是我的 html 表单页面

{% extends 'layout.html' %}

{% block body_block %}
{% include '_messages.html' %}
<div class="container">
    <div class="row">
    <div class="col-md-2"></div>
    <div class="col-md-8">
        <h2 class="text-center bg-info p-2">
            Add product
        </h2>
        {% from '_formhelpers.html' import render_field %}
        <form action="" method="POST" enctype="multipart/form-data">
            {{ render_field(form.name, class="form-control", placeholder="Product Name")}}
            {{ render_field(form.price, class="form-control", placeholder="Price") }}
            {{ render_field(form.stock, class="form-control", placeholder="Stock") }}
            <label for="brand">Add a Brand</label>
            <select class="form-control" name="brand" id="brand">
                <option value="" class="form-control" required> Select a Brand</option>
                {% for brand in brands%}
                    <option value="brand.id" class="form-control">{{brand.name}}</option>
                {% endfor %}
            </select>
            <label for="category">Add a Category</label>
            <select class="form-control" name="category" id="category">
                <option value="" class="form-control" required> Select a Category</option>
                {% for category in categories %}
                    <option value="category.id" class="form-control">{{category.name}}</option>
                {% endfor %}
            </select>
            {{ render_field(form.desc, class="form-control", placeholder="Product Description", rows=10) }}
            <div class="container">
                <div class="row">
                    <div class="col-md-4">
                        {{ render_field(form.image_1, class="form-control")}}
                    </div>
                    <div class="col-md-4">
                        {{ render_field(form.image_2, class="form-control")}}
                    </div>
                    <div class="col-md-4">
                        {{ render_field(form.image_3, class="form-control")}}
                    </div>
                </div>
            </div>

            <button type="submit" class="btn btn-outline-info mt-4">Add Product</button>
        </form>
    </div>
    <div class="col-md-2"></div>
</div>
</div>
{% endblock body_block %}

我在下面简化了您的示例。错误发生在第 5 行:

image_1 = photos.save()
image_2 = photos.save()
image_3 = photos.save()
print(f"Image 1 name:{image_1}, its type:{type(image_1)}")
product = Product(brand=brand, category=category)           # <- HERE
db.session.add(product)

既然你提到它正在将图像保存到目录中,这表明前 3 行是成功的。并且没有向数据库添加任何内容,表明错误在第 4 行和第 6 行之间。

由于您在 models.py 中指定属性 brandcategory 是关系属性 (db.relationship()) 这些属性需要一个 ORM 对象,并且您正在向他们传递一个字符串。

在将 ORM 对象传递给 Product 之前实例化它们,如下所示:

brand = Brand(name="brandname")
category = Category(name="categoryname")

product = Product(brand=brand, category=category)

这就是这个答案中的内容,可以理解这是一篇很长的文章: