Conflicts with relationship between tables

Question:

I’ve been constantly getting a warning on the console and I’m going crazy from how much I’ve been reading but I haven’t been able to resolve this:

SAWarning: relationship ‘Book.users’ will copy column user.uid to column user_book.uid, which conflicts with relationship(s): ‘User.books’ (copies user.uid to user_book.uid). If this is not intention, consider if these relationships should be linked with back_populates, or if viewonly=True should be applied to one or more if they are read-only. For the less common case that foreign key constraints are partially overlapping, the orm.foreign() annotation can be used to isolate the columns that should be written towards. The ‘overlaps’ parameter may be used to remove this warning.

The tables the console cites in this notice are as follows:

user_book = db.Table('user_book',
                     db.Column('uid', db.Integer, db.ForeignKey('user.uid'), primary_key=True),
                     db.Column('bid', db.Text, db.ForeignKey('book.bid'), primary_key=True),
                     db.Column('date_added', db.DateTime(timezone=True), server_default=db.func.now())
                     )


class User(db.Model):
    __tablename__ = 'user'

    uid = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(25), nullable=False)
    hash = db.Column(db.String(), nullable=False)
    first_name = db.Column(db.String(30), nullable=True)
    last_name = db.Column(db.String(80), nullable=True)
    books = db.relationship('Book', secondary=user_book)

class Book(db.Model):
    __tablename__ = 'book'

    bid = db.Column(db.Text, primary_key=True)
    title = db.Column(db.Text, nullable=False)
    authors = db.Column(db.Text, nullable=False)
    thumbnail = db.Column(db.Text, nullable=True)
    users = db.relationship('User', secondary=user_book)

I use the user_book table to show the user the books he has added.

What am I missing? I take this opportunity to ask, semantically the relationship between tables and foreign keys is being done correctly?

Asked By: ARNON

||

Answers:

As the warning message suggests, you are missing the back_populates= attributes in your relationships:

class User(db.Model):
# …
    books = db.relationship('Book', secondary=user_book, back_populates="users")
# …
    
class Book(db.Model):
# …
    users = db.relationship('User', secondary=user_book, back_populates="books")
# …
Answered By: Gord Thompson

I kind of figure this out.
As the code in official tutorial.

from sqlalchemy import Column, ForeignKey, Integer, String, Table
from sqlalchemy.orm import declarative_base, relationship

Base = declarative_base()


class User(Base):
    __tablename__ = "user"
    id = Column(Integer, primary_key=True)
    name = Column(String(64))
    kw = relationship("Keyword", secondary=lambda: user_keyword_table)

    def __init__(self, name):
        self.name = name


class Keyword(Base):
    __tablename__ = "keyword"
    id = Column(Integer, primary_key=True)
    keyword = Column("keyword", String(64))

    def __init__(self, keyword):
        self.keyword = keyword


user_keyword_table = Table(
    "user_keyword",
    Base.metadata,
    Column("user_id", Integer, ForeignKey("user.id"), primary_key=True),
    Column("keyword_id", Integer, ForeignKey("keyword.id"), primary_key=True),
)

Doesn’t it make you wander why the relationship only exists in User class rather than both class ?

The thing is, it automatically creates the reverse relationship in Keyword class (a "backref=’users’ liked parameter is required I supposed ?)

Answered By: Steven Hu
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.