问题
I am having trouble configuring a simple relationship. I managed to get it working reasonably well with the use of a simple association table but I wanted extra 'meta' fields so I am looking into using an association object pattern. (Yes I am a DB novice)
from flask.ext.sqlalchemy import SQLAlchemy
from flask import Flask
import os
import re
import datetime
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = False
db = SQLAlchemy(app)
class NewsletterInfo(db.Model):
__tablename__ = 'newsletter_info'
id = db.Column(db.Integer, primary_key = True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
newsletter_id = db.Column(db.Integer, db.ForeignKey('newsletter.id'))
date_added = db.Column(db.DateTime, default=datetime.datetime.now)
date_modified = db.Column(db.DateTime, default=datetime.datetime.now)
note = db.Column(db.String(140))
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(128), unique=True)
password = db.Column(db.String(128))
date_registered = db.Column(db.DateTime, default=datetime.datetime.now)
email_verified = db.Column(db.Boolean, default=False)
newsletters = db.relationship('NewsletterInfo')
class Newsletter(db.Model):
__tablename__ = 'newsletter'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
category = db.Column(db.String(36))
price = db.Column(db.String)
You can ignore the use of flask here completely.
I basically want each user to be able to track as many newsletters as they want. And each User>>Newsletter connection will have some meta information such as when they first added it and even an optional note.
I do get this error when trying to do "my_user.newsletters.append(my_newsletter)"
Attempting to flush an item of type <class 'Newsletter'> as a member of collection "User.newsletters". Expected an
object of type <class 'NewsletterInfo'> or a polymorphic subclass of this type.
This worked for the original table I made but obviously I am doing something quite wrong with this slightly more complicated setup.
Could anyone help me with the relationship I am trying to configure? I am also concerned it is a badly conceived relationship anyway so would appreciate advice on the standard relationship setup for this.
回答1:
The error is because you have made a relationship to NewsletterInfo
, not Newsletter
, so this is obviously the type that the collection expects.
A many-to-many association with meta information is not uncommon. To continue using it as if it were a regular relationship via User.newsletters
, you will have to set up an association proxy. Have a look at the first example. The important parts are these:
class User(db.Model):
# ...
newsletters = association_proxy('user_newsletters', 'newsletter')
class NewsletterInfo(db.Model):
# ...
user = relationship(User, backref=backref("user_newsletters"))
newsletter = relationship("Newsletter")
来源:https://stackoverflow.com/questions/27999934/sqlalchemy-many-to-many-relationship-association-object