三个表上的SQL Alchemy外键参考

时间:2019-01-23 05:09:38

标签: flask flask-sqlalchemy

我正在使用带有sql-alchemy数据库的flask创建一个网站。我有三个带有外键互相引用的表。如何通过引用两个外键从第一张表中获取用户名和电话?我的代码如下:

models.py

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)  
    password = db.Column(db.String(60), unique=True, nullable=False)
    phone = db.Column(db.Integer, nullable=True)
    user_role = db.Column(db.String(20), nullable=False)
    image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
    pgs = db.relationship('PGInfo', backref='owner', lazy=True)
    bookedpgs = db.relationship('PGBooked', backref='customer', lazy=True)

    def __repr__(self):
        return f"User('{self.username}', '{self.email}')"


class PGInfo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    owner_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    pg_name = db.Column(db.String(200), nullable=False)
    date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    location_info = db.Column(db.String(120), unique=True, nullable=False)
    body = db.Column(db.Text, nullable=False)
    price = db.Column(db.Integer, nullable=False)
    image_file = db.Column(db.String(20), nullable=False, default='default.jpg')


    def __repr__(self):
        return f"PGInfo('{self.pg_name}', '{self.date_posted}', '{self.location_info}', '{self.price}', '{self.image_file}')"

class PGBooked(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    customer_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    pg_id = db.Column(db.Integer, db.ForeignKey(PGInfo.id), nullable=False)
def __repr__(self):
        return f"PGBooked('{self.name}')"

routes.py

def book_pg(pg_id):        
    bookedpg = PGBooked(customer=current_user, owner=PGInfo.owner_id.username, pg_name=PGInfo.pg_name, location=PGInfo.location_info, phone=PGInfo.owner_id.phone)
    db.session.add(bookedpg)
    db.session.commit()
    flash("You have booked the pg!", 'success')        
    return render_template('bookpg.html', title='Book PG')

bookpg.html

{% extends "layout.html" %}
{% block content %}

  {{ bookedpg.customer }}
  {{ bookedpg.owner }}
  {{ bookedpg.pg_name }}
  {{ bookedpg.location }}
  {{ bookedpg.phone }}

{% endblock content %}

错误

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with PGInfo.owner_id has an attribute 'username'

那么如何根据上述关系获取用户名?预先谢谢你!

1 个答案:

答案 0 :(得分:0)

错误出在 models.py 文件中。正确的代码如下:

models.py

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(200), unique=True, nullable=False)
    email = db.Column(db.String(200), unique=True, nullable=False)  
    password = db.Column(db.String(60), unique=True, nullable=False)
    phone = db.Column(db.Integer, nullable=True)
    user_role = db.Column(db.String(20), nullable=False)
    image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
    pgs = db.relationship('PGInfo', backref='owner', lazy=True)
    bookedpgs = db.relationship('PGBooked', backref='customer', lazy=True)

    def __repr__(self):
        return f"User('{self.username}', '{self.email}')"


class PGInfo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    owner_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    pg_name = db.Column(db.String(200), nullable=False)
    date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    location_info = db.Column(db.String(200), nullable=False)
    body = db.Column(db.Text, nullable=False)
    price = db.Column(db.Integer, nullable=False)
    image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
    pg = db.relationship('PGBooked', backref='pg', lazy=True)


    def __repr__(self):
        return f"PGInfo('{self.pg_name}', '{self.date_posted}', '{self.location_info}', '{self.price}', '{self.image_file}')"

class PGBooked(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    customer_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    pg_id = db.Column(db.Integer, db.ForeignKey(PGInfo.id))
    name = db.Column(db.String(200), nullable=False)
    location_info =  db.Column(db.String(200), nullable=False)
    owner = db.Column(db.String(200), nullable=False)
    phone =  db.Column(db.Integer)

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

我必须在PGInfo表和PGBooked表之间创建一个关系。

routes.py

@app.route("/pg/<int:pg_id>/book_pg", methods=['GET','POST'])
@login_required
def book_pg(pg_id):
    if current_user.is_authenticated:    
        pg = PGInfo.query.get_or_404(pg_id)   
        bookedpg = PGBooked(customer=current_user, name=pg.pg_name, location_info=pg.location_info, owner=pg.owner.username, phone=pg.owner.phone)        
        db.session.add(bookedpg)
        db.session.commit()        
        # db.session.delete(pg)
        # db.session.commit()
        flash("You have booked the pg!", 'success')
        return redirect(url_for('display_booked_pgs'))


@app.route("/booked_pgs", methods=['GET', 'POST'])
@login_required
def display_booked_pgs():
    bookedpgs = PGBooked.query.filter_by(customer_id=current_user.id).all()     
    # bookedpgs_dict = dict((col, getattr(bookedpgs, col)) for col in bookedpgs.__table__.columns.keys())     
    return render_template('bookedpg.html', title='Booked PGs', bookedpgs=bookedpgs)

然后我可以通过如下循环显示在模板中:

bookpg.html

{% extends "layout.html" %}

{% block content %}
  <div>           
    {% for item in bookedpgs %}  
           <p> {{ item.__dict__ }} </p>      
    {% endfor %}             
  </div>
{% endblock content %}