How to create a field with a list of foreign keys in SQLAlchemy?

2024/10/6 8:23:49

I am trying to store a list of models within the field of another model. Here is a trivial example below, where I have an existing model, Actor, and I want to create a new model, Movie, with the field Movie.list_of_actors:

import uuidfrom sqlalchemy import Boolean, Column, Integer, String, DateTime
from sqlalchemy.schema import ForeignKey
rom sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationshipBase = declarative_base()class Actor(Base):__tablename__ = 'actors'id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)name = Column(String)nickname = Column(String)academy_awards = Column(Integer)# This is my new model:
class Movie(Base):__tablename__ = 'movies'id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)title = Column(String)# How do I make this a list of foreign keys???list_of_actors = Column(UUID(as_uuid=True), ForeignKey('actors.id'))

I understand that this can be done with a many-to-many relationship, but is there a more simple solution? Note that I don't need to look up which Movie's an Actor is in - I just want to create a new Movie model and access the list of my Actor's. And ideally, I would prefer not to add any new fields to my Actor model.

I've gone through the tutorials using the relationships API, which outlines the various one-to-many/many-to-many combinations using back_propagates and backref here: http://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html But I can't seem to implement my list of foreign keys without creating a full-blown many-to-many implementation.

But if a many-to-many implementation is the only way to proceed, is there a way to implement it without having to create an "association table"? The "association table" is described here: http://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#many-to-many ? Either way, an example would be very helpful!


Also, if it matters, I am using Postgres 9.5. I see from this post there might be support for arrays in Postgres, so any thoughts on that could be helpful.

Update

It looks like the only reasonable approach here is to create an association table, as shown in the selected answer below. I tried using ARRAY from SQLAlchemy's Postgres Dialect but it doesn't seem to support Foreign Keys. In my example above, I used the following column:

list_of_actors = Column('actors', postgresql.ARRAY(ForeignKey('actors.id')))

but it gives me an error. It seems like support for Postgres ARRAY with Foreign Keys is in progress, but still isn't quite there. Here is the most up to date source of information that I found: http://blog.2ndquadrant.com/postgresql-9-3-development-array-element-foreign-keys/

Answer

If you want many actors to be associated to a movie, and many movies be associated to an actor, you want a many-to-many. This means you need an association table. Otherwise, you could chuck away normalisation and use a NoSQL database.

An association table solution might resemble:

class Actor(Base):__tablename__ = 'actors'id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)name = Column(String)nickname = Column(String)academy_awards = Column(Integer)class Movie(Base):__tablename__ = 'movies'id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)title = Column(String)actors = relationship('ActorMovie', uselist=True, backref='movies')class ActorMovie(Base):__tablename__ = 'actor_movies'actor_id = Column(UUID(as_uuid=True), ForeignKey('actors.id'))movie_id = Column(UUID(as_uuid=True), ForeignKey('movies.id'))

If you don't want ActorMovie to be an object inheriting from Base, you could use sqlachlemy.schema.Table.

https://en.xdnf.cn/q/70384.html

Related Q&A

Implementing a recursive algorithm in pyspark to find pairings within a dataframe

I have a spark dataframe (prof_student_df) that lists student/professor pair for a timestamp. There are 4 professors and 4 students for each timestamp and each professor-student pair has a “score” (s…

Python Delegate Pattern - How to avoid circular reference?

I would to ask if using the Delegate Pattern in Python would lead to circular references and if so, what would be the best way to implement it to ensure the object and its delegate will be garbage coll…

Render Jinja after jQuery AJAX request to Flask

I have a web application that gets dynamic data from Flask when a select element from HTML is changed. of course that is done via jquery ajax. No probs here I got that.The problem is, the dynamic data …

shape-preserving piecewise cubic interpolation for 3D curve in python

I have a curve in 3D space. I want to use a shape-preserving piecewise cubic interpolation on it similar to pchip in matlab. I researched functions provided in scipy.interpolate, e.g. interp2d, but …

ForeignKey vs OneToOne field django [duplicate]

This question already has answers here:OneToOneField() vs ForeignKey() in Django(12 answers)Closed 9 years ago.I need to extend django user with some additional fields . I found 2 different ways there…

How to sort glob.glob numerically?

I have a bunch of files sorted numerically on a folder, when I try to sort glob.glob I never get the files in the right order.file examples and expected output sorting folder ------ C:\Users\user\Deskt…

How to determine a numpy-array reshape strategy

For a python project I often find myself reshaping and re-arranging n-dimensional numpy arrays. However, I have a hard time to determine how to approach the problem, visualize the outcome of the result…

matplotlib plotting multiple lines in 3D

I am trying to plot multiple lines in a 3D plot using matplotlib. I have 6 datasets with x and y values. What Ive tried so far was, to give each point in the data sets a z-value. So all points in data …

How to get a telegram private channel id with telethon

Hi cant figure out how to solve this problem, so any help will be really appreciated. Im subscribed to a private channel. This channel has no username and I dont have the invite link (the admin just ad…

boolean mask in pandas panel

i am having some trouble masking a panel in the same way that I would a DataFrame. What I want to do feels simple, but I have not found a way looking at the docs and online forums. I have a simple ex…