Python Flask-sqlalchemy 关系错误信息

问题描述 投票:0回答:1

我对 Flask 并不陌生,但我第一次决定使用

flask-sqlalchemy
,而不是只为每个项目编写自己的 Orm。现在我遇到了一个问题,但我就是不知道如何解决它。


Traceback (most recent call last):
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\flask\app.py", line 2190, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\flask\app.py", line 1486, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\flask\app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\flask\app.py", line 1469, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\app.py", line 31, in register
    user = User(
           ^^^^^
  File "<string>", line 4, in __init__
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\state.py", line 561, in _initialize_instance
    manager.dispatch.init(self, args, kwargs)
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\event\attr.py", line 487, in __call__
    fn(*args, **kw)
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\mapper.py", line 4391, in _event_on_init
    instrumenting_mapper._check_configure()
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\mapper.py", line 2386, in _check_configure
    _configure_registries({self.registry}, cascade=True)
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\mapper.py", line 4199, in _configure_registries
    _do_configure_registries(registries, cascade)
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\mapper.py", line 4240, in _do_configure_registries
    mapper._post_configure_properties()
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\mapper.py", line 2403, in _post_configure_properties
    prop.init()
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\interfaces.py", line 579, in init
    self.do_init()
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\relationships.py", line 1639, in do_init
    self._generate_backref()
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\relationships.py", line 2128, in _generate_backref
    self._add_reverse_property(self.back_populates)
  File "C:\Users\Flinn\OneDrive\Dokumente\MusicStore\VENV3.11.1\Lib\site-packages\sqlalchemy\orm\relationships.py", line 1595, in _add_reverse_property
    raise sa_exc.ArgumentError(
sqlalchemy.exc.ArgumentError: reverse_property 'orchestra_memberships' on relationship OrchestraMembership.user references relationship User.orchestra_memberships, which does not reference mapper Mapper[OrchestraMembership(orchestra_memberships)]

我知道这是一条很长的错误消息,可能所有这些都不是很重要,但为了澄清起见,我还将在这里发布 Flask 应用程序中的其余代码:

app.py:


import flask
from models import db  # Import the SQLAlchemy db object
from models import User, Orchestra, OrchestraMembership
from flask_bcrypt import Bcrypt

app = flask.Flask(__name__)
app.config[
    "SQLALCHEMY_DATABASE_URI"
] = r"sqlite:///C:\Users\Flinn\OneDrive\Dokumente\MusicStore\database.db"

db.init_app(app)
bcrypt = Bcrypt(app)


@app.route("/")
def index():
    return flask.render_template("index.html")


@app.route("/register", methods=["GET", "POST"])
def register():
    if flask.request.method == "POST":
        full_name = flask.request.form["full_name"]
        username = flask.request.form["username"]
        email = flask.request.form["email"]
        password = flask.request.form["password"]

        hashed_password = bcrypt.generate_password_hash(password).decode("utf-8")

        # Create a new user
        user = User(
            full_name=full_name,
            username=username,
            email=email,
            password_hash=hashed_password,
        )
        db.session.add(user)
        db.session.commit()

        flask.flash("Registration successful. You can now log in.", "success")
        return flask.redirect(url_for("login"))


@app.route("/login", methods=["GET", "POST"])
def login():
    if flask.request.method == "POST":
        email = flask.request.form["email"]
        password = flask.request.form["password"]

        user = User.query.filter_by(email=email).first()

        if user and bcrypt.check_password_hash(user.password_hash, password):
            # Log in the user
            flask.flash("Login successful.", "success")
            return flask.redirect(url_for("profile"))
        else:
            flask.flash("Login failed. Please check your email and password.", "error")

    return flask.render_template("login.html")


@app.route("/profile")
def profile():
    # Implement your profile view here
    return "User Profile"


if __name__ == "__main__":
    app.run()

models.py:

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime

db = SQLAlchemy()


user_orchestra_association = db.Table(
    "user_orchestra_association",
    db.Column("user_id", db.Integer, db.ForeignKey("users.id")),
    db.Column("orchestra_id", db.Integer, db.ForeignKey("orchestra_memberships.id")),
)


class OrchestraMembership(db.Model):
    __tablename__ = "orchestra_memberships"

    id = db.Column(Integer, primary_key=True)
    user_id = db.Column(Integer, ForeignKey("users.id"))
    orchestra_id = db.Column(Integer, ForeignKey("orchestra_memberships.id"))
    """
    role = db.Column(String)
    instruments_played = db.Column(String)  # Comma-separated list or JSON array.
    """
    user = relationship("User", back_populates="orchestra_memberships")
    orchestra = relationship("Orchestra", back_populates="orchestra_memberships")


class User(db.Model):
    __tablename__ = "users"

    id = db.Column(Integer, primary_key=True)
    """
    full_name = db.Column(String)
    username = db.Column(String)
    email = db.Column(String, unique=True)
    password_hash = db.Column(String)
    profile_picture = db.Column(String)  # URL or File Path
    """
    # short_description = db.Column(String)
    # ... add other columns as needed.

    # Define a one-to-many relationship with VerificationToken
    verification_tokens = relationship("VerificationToken", back_populates="user")

    orchestra_memberships = relationship(
        "Orchestra", secondary=user_orchestra_association, back_populates="members"
    )


class Orchestra(db.Model):
    __tablename__ = "orchestras"

    id = db.Column(Integer, primary_key=True)
    ## name = db.Column(String)
    # ... add other columns as needed.

    members = relationship(
        "User",
        secondary=user_orchestra_association,
        back_populates="orchestra_memberships",
    )


class VerificationToken(db.Model):
    __tablename__ = "verification_tokens"

    id = db.Column(Integer, primary_key=True)
    user_id = db.Column(Integer, ForeignKey("users.id"))
    token = db.Column(String, unique=True)
    expiry_timestamp = db.Column(db.DateTime, default=datetime.utcnow)

    # Define a many-to-one relationship with User
    user = relationship("User", back_populates="verification_tokens")


class PasswordResetToken(db.Model):
    __tablename__ = "password_reset_tokens"

    id = db.Column(Integer, primary_key=True)
    user_id = db.Column(Integer, ForeignKey("users.id"))
    token = db.Column(String, unique=True)
    expiry_timestamp = db.Column(db.DateTime, default=datetime.utcnow)

    # Define a many-to-one relationship with User
    user = relationship("User", back_populates="password_reset_tokens")

然后,当我运行测试脚本来注册新帐户时,会发生错误。

register_new_account_test.py:

import requests
import random
import string

# Define the base URL of your Flask application
base_url = "http://localhost:5000"  # Change this to your application's URL


# Generate a random username, email, and password
def generate_random_string(length):
    characters = string.ascii_letters + string.digits
    return "".join(random.choice(characters) for _ in range(length))


random_username = generate_random_string(8)
random_email = generate_random_string(8) + "@example.com"
random_password = generate_random_string(12)

# Create a random user
user_data = {
    "full_name": "Random User",
    "username": random_username,
    "email": random_email,
    "password": random_password,
}

registration_url = base_url + "/register"  # Replace with your registration endpoint URL

# Send a POST request to register the user
response = requests.post(registration_url, data=user_data)

if response.status_code == 200:
    print("User registration successful.")
    print(f"Username: {random_username}")
    print(f"Email: {random_email}")
    print(f"Password: {random_password}")
else:
    print("User registration failed.")
    print("Response status code:", response.status_code)
    print("Response content:", response.text)

如果有人可以向我解释错误消息,并提供一些有关如何修复它的信息,我将非常感激。我已经阅读了一些文档,但我还没有真正理解所有内容。如果您有任何疑问请询问。

我尝试使用 FLASK-SQLALCHEMY 创建数据库 orm,但我只是收到错误而不是工作数据库

python flask-sqlalchemy
1个回答
0
投票

简单的答案是,你们的关系不匹配:

OrchestraMembership.user
指向
User.orchestra_memberships
,但
User.orchestra_memberships
指向
Orchestra
模型。

退一步看,您的数据模型似乎不太正确。

orchestra_user_association
OrchestraMembership
似乎扮演着类似的角色?也许您需要删除其中之一,例如删除
OrchestraMembership
并让
orchestra_user_association.orchestra_id
指向
orchestra.id

© www.soinside.com 2019 - 2024. All rights reserved.