SQLAlchemy many to many relationship & Association object

孤街浪徒 提交于 2019-12-14 04:10:27

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!