一对一关系DB模型无法正常工作

时间:2018-02-28 00:51:36

标签: python sqlalchemy flask-sqlalchemy

背景

我有一个用户可以上传文件的项目。在数据库中,我想将文件路径存储到上传的文件中。

DB中有2个表; Users& FileUploadPath。这些表格具有一对一的关系。

我目前使用的Flask-SQLAlchemy模型是:

import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////{}'.format(os.path.join(os.getcwd(), "test.db"))
db = SQLAlchemy(app)


class User(db.Model):

    __tablename__ = 'Users'

    userid = db.Column(db.Integer, primary_key=True, autoincrement=True)
    fname = db.Column(db.String(80), nullable=False)
    lname = db.Column(db.String(80), nullable=False)
    phonenum = db.Column(db.String(10), nullable=False)
    email = db.Column(db.String(60), nullable=False)
    password = db.Column(db.String(60), nullable=False)
    validated = db.Column(db.Boolean, default=False)

    child = db.relationship('FileUploadPath', uselist=False, backref='Users')


class FileUploadPath(db.Model):

    __tablename__ = 'FileUploadPath'

    fileUploadID = db.Column(db.Integer, primary_key=True, autoincrement=True)
    w9FilePath = db.Column(db.String(60), nullable=False)
    gcFilePath = db.Column(db.String(60), nullable=False)
    livescanFilePath = db.Column(db.String(60), nullable=False)
    gcaFilePath = db.Column(db.String(60), nullable=False)

    userID = db.Column(db.Integer, db.ForeignKey('Users.userid'))

要创建新用户,请使用以下命令:

newuser = User(fname='Bob', lname='Smith', phonenum='6551234567', email='bobsmith@gmail.com', password='fe287943hfbwiqey281')

使用此命令,我希望在userID表中看到FileUploadPath;目前仅在Users表中看到已创建的用户,但在NULL列中只看到userID

通过查询,我还希望查看与特定用户相关的所有上传文件路径信息。

模型设置之间的关系是否正确?如果没有,我将如何宣布这种关系?

修改

我想要做的是将fileUploadID存储在Users表内。应为每个创建的新用户插入FileUploadPath表中的新行。因为当我创建一个新用户时,FileUploadPath表中的所有列都将为空;因为新用户尚未上传任何文件。

1 个答案:

答案 0 :(得分:1)

表关系看起来没问题,除了backref='Users'是一个奇怪的名称选择,因为这将向FileUploadPath添加“用户”属性,这不遵循命名约定其余的属性。我希望这可能是backref='user'

现在,主要问题是您没有指定FileUploadPath应该与newuser相关联,因此它没有在引用ID的FileUploadPath中插入任何条目newuser。或者您可能已插入了要与FileUploadPath关联的新newuser,但您未在示例中显示该代码。在任何情况下,它都不知道哪个FileUploadPath与哪个User相关联,并且它不会为每个FileUploadPath自动创建新的User,所以当您只需创建一个新的User,或者如果您单独创建新的UserFileUploadPath但未链接它们,则最终不会与FileUploadPath相关联您的新User

因此,您需要做的是通过添加FileUploadPath参数将newuserchild=newFileUploadPath相关联(其中newFileUploadPath是已构建的FileUploadPath User }}当您调用User构造函数,或单独构建和添加FileUploadPathnewuser.child = newFileUploadPath个对象,并设置newFileUploadPath.user = newusernewFileUploadPath.user时。 (请注意,backref='user'会假设我的建议FileUploadPath更改。)

修改:这是MVCE,其中显示了如何为用户添加文件上传。但是,最初创建用户时文件上载不存在,这应该是预期的行为。你绝对不应该在uselist=False中包含所有空字符串的条目。此外,如果您计划每个用户最多允许上传4次,则需要通过删除Users.child并将children视为列表来使其成为多对一关系,并且也许还可以将其重命名为uploadsimport os import sys from sqlalchemy import Column, ForeignKey, Integer, String, Boolean from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship, sessionmaker from sqlalchemy import create_engine Base = declarative_base() class User(Base): __tablename__ = 'Users' userid = Column(Integer, primary_key=True, autoincrement=True) fname = Column(String(80), nullable=False) lname = Column(String(80), nullable=False) phonenum = Column(String(10), nullable=False) email = Column(String(60), nullable=False) password = Column(String(60), nullable=False) validated = Column(Boolean, default=False) child = relationship('FileUploadPath', uselist=False, backref='user') class FileUploadPath(Base): __tablename__ = 'FileUploadPath' fileUploadID = Column(Integer, primary_key=True, autoincrement=True) w9FilePath = Column(String(60), nullable=False) gcFilePath = Column(String(60), nullable=False) livescanFilePath = Column(String(60), nullable=False) gcaFilePath = Column(String(60), nullable=False) userID = Column(Integer, ForeignKey('Users.userid')) engine = create_engine('sqlite:///') Base.metadata.create_all(engine) session_factory = sessionmaker(bind=engine) session = session_factory() # Insert a new user with no uploads: newuser = User(fname='Bob', lname='Smith', phonenum='6551234567', email='bobsmith@gmail.com', password='fe287943hfbwiqey281') session.add(newuser) session.commit() # Query for users and uploads: print(session.query(FileUploadPath).count()) # 0 print(session.query(User).count()) # 1 print(session.query(User).one().child) # None # Insert an upload for the user: newupload = FileUploadPath(w9FilePath='some_path', gcFilePath='another_path', livescanFilePath='yet_another_path', gcaFilePath='another_path_still', user=newuser) session.add(newupload) session.commit() # Again, query for users and uploads: print(session.query(FileUploadPath).count()) # 1 print(session.query(User).one().child) # <FileUploadPath object> print(session.query(User).one().child.w9FilePath) # 'some_path'

(注意,此示例使用纯SQLAlchemy而不是Flask-SQLAlchemy,因此模型定义和数据库设置的某些部分可能与您的实现不同。)

CFRelease