简体   繁体   中英

Peewee - Access an intermediary table easily

Say I have peewee models like so:

class Users(_BaseModel):
    id = AutoField(primary_key=True, null=False, unique=True)

    first_name = CharField(null=False)
    last_name = CharField(null=False)
    # Cut short for clarity

class Cohorts(_BaseModel):
    id = AutoField(primary_key=True, null=False, unique=True)
    name = CharField(null=False, unique=True)
    # Cut short for clarity

class CohortsUsers(_BaseModel):
    cohort = ForeignKeyField(Cohorts)
    user = ForeignKeyField(Users)
    is_primary = BooleanField(default=True)

I need to access easily from the user what cohort they are in and for example the cohort's name. If a user could be in just one cohort, it would be easy but here, having it be many2many complicates things.

Here's what I got so far, which is pretty ugly and inefficient

Users.select(Users, CohortsUsers).join(CohortsUsers).where(Users.id == 1)[0].cohortsusers.cohort.name

Which will do what I require it to but I'd like to find a better way to do it.

Is there a way to have it so I can do Users.get_by_id(1).cohort.name ?

EDIT: I'm thinking about making methods to access them easily on my Users class but I am not really sure it's the best way of doing it nor how to go about it

If it do it like so, it's quite ugly because of the import inside the method to avoid circular imports

@property
def cohort(self):
    from dst_datamodel.cohorts import CohortsUsers
    return Users.select(Users, CohortsUsers).join(CohortsUsers).where(Users.id == self.id)[0].cohortsusers.cohort

But having this ugly method allows me to do Users.get_by_id(1).cohort easily

This is all covered in the documentation here: http://docs.peewee-orm.com/en/latest/peewee/relationships.html#implementing-many-to-many

You have a many-to-many relationship, where a user can be in zero, one or many cohorts, and a cohort may have zero, one or many users.

If there is some invariant where a user only has one cohort, then just do this:

# Get all cohorts for a given user id and print their name(s).
q = Cohort.select().join(CohortUsers).where(CohortUsers.user == some_user_id)
for cohort in q:
    print(cohort.name)

More specific to your example:

@property
def cohort(self):
    from dst_datamodel.cohorts import CohortsUsers
    cohort = Cohort.select().join(CohortsUsers).where(CohortUsers.user == self.id).get()
    return cohort.name

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM