Peewee: How to design models in a ManyToManyField with a through_model

Created on 10 Nov 2015  路  1Comment  路  Source: coleifer/peewee

(new to peewee/python orms, coming from a "legacy" rails database)

I'm trying to model 2 elements in a many to many relationship, using a join table;
I have a User and a Project, and a join table called ProjectUser.

I've tried this, and I'm getting circular dependency errors because as is ProjectUser is not defined in Project, and if I swap where I define each, then Project isn't defined in ProjectUser:

# models/projects.py
from peewee import *
from playhouse.fields import ManyToManyField

from . import users as u

class Project(BaseModel):
  name = CharField(null=True)
  users = ManyToManyField(u.User, related_name='projects', through_model=ProjectUser)

  class Meta:
    db_table = 'projects'

class ProjectUser(BaseModel):
  project = ForeignKeyField(Project, db_column='project_id', index=True, null=True)
  user = ForeignKeyField(u.User, db_column='user_id', index=True, null=True)

  class Meta:
    db_table = 'project_users'

# models/users.py
class User(BaseModel):
  email = CharField(unique=True)

When I let peewee determine the table name (by removing the through_model param), it seems to be ok, but obviously my join table isn't named correctly that way.

Can the ForeignKeyField declarations in the ProjectUser model be defined dynamically so I can avoid the circular dependency? Or phrased differently, how would I accomplish this with a custom-named through_model table?

or or... am I just not thinking about this correctly?

TIA!

ps all my models were generated by using pwiz on my rails database.

Most helpful comment

You can use the Proxy object see circular foreign keys.

class User(BaseModel):
  email = CharField(unique=True)

ProjectUserProxy = Proxy()

class Project(BaseModel):
  name = CharField(null=True)
  users = ManyToManyField(
    User, 
    related_name='projects', 
    through_model=ProjectUserProxy)

  class Meta:
    db_table = 'projects'

class ProjectUser(BaseModel):
  project = ForeignKeyField(Project, db_column='project_id', index=True, null=True)
  user = ForeignKeyField(User, db_column='user_id', index=True, null=True)

  class Meta:
    db_table = 'project_users'

ProjectUserProxy.initialize(ProjectUser)

Everything worked correctly with the above code when I tried creating some users, projects, and the relationships between them. The custom through table appeared to be working as well.

>All comments

You can use the Proxy object see circular foreign keys.

class User(BaseModel):
  email = CharField(unique=True)

ProjectUserProxy = Proxy()

class Project(BaseModel):
  name = CharField(null=True)
  users = ManyToManyField(
    User, 
    related_name='projects', 
    through_model=ProjectUserProxy)

  class Meta:
    db_table = 'projects'

class ProjectUser(BaseModel):
  project = ForeignKeyField(Project, db_column='project_id', index=True, null=True)
  user = ForeignKeyField(User, db_column='user_id', index=True, null=True)

  class Meta:
    db_table = 'project_users'

ProjectUserProxy.initialize(ProjectUser)

Everything worked correctly with the above code when I tried creating some users, projects, and the relationships between them. The custom through table appeared to be working as well.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kalimalrazif picture kalimalrazif  路  3Comments

lucasrc picture lucasrc  路  5Comments

rayzorben picture rayzorben  路  4Comments

christianmalek picture christianmalek  路  4Comments

megachweng picture megachweng  路  3Comments