importdatabasesimportsqlalchemyimportormardatabase=databases.Database("sqlite:///db.sqlite")metadata=sqlalchemy.MetaData()classDepartment(ormar.Model):classMeta:database=databasemetadata=metadataid:ormar.Integer(primary_key=True)name:ormar.String(max_length=100)classCourse(ormar.Model):classMeta:database=databasemetadata=metadataid:ormar.Integer(primary_key=True)name:ormar.String(max_length=100)completed:ormar.Boolean(default=False)department:ormar.ForeignKey(Department)department=Department(name='Science')# set up a relation with actual Model instancecourse=Course(name='Math',completed=False,department=department)# set up relation with only related model pk valuecourse2=Course(name='Math II',completed=False,department=department.pk)# set up a relation with dictionary corresponding to related modelcourse3=Course(name='Math III',completed=False,department=department.dict())# explicitly set up Nonecourse4=Course(name='Math III',completed=False,department=None)
Primary key value
You can setup the relation also with just the pk column value of the related model.
importdatabasesimportsqlalchemyimportormardatabase=databases.Database("sqlite:///db.sqlite")metadata=sqlalchemy.MetaData()classDepartment(ormar.Model):classMeta:database=databasemetadata=metadataid:ormar.Integer(primary_key=True)name:ormar.String(max_length=100)classCourse(ormar.Model):classMeta:database=databasemetadata=metadataid:ormar.Integer(primary_key=True)name:ormar.String(max_length=100)completed:ormar.Boolean(default=False)department:ormar.ForeignKey(Department)department=Department(name='Science')# set up a relation with actual Model instancecourse=Course(name='Math',completed=False,department=department)# set up relation with only related model pk valuecourse2=Course(name='Math II',completed=False,department=department.pk)# set up a relation with dictionary corresponding to related modelcourse3=Course(name='Math III',completed=False,department=department.dict())# explicitly set up Nonecourse4=Course(name='Math III',completed=False,department=None)
Dictionary
Next option is with a dictionary of key-values of the related model.
You can build the dictionary yourself or get it from existing model with dict() method.
importdatabasesimportsqlalchemyimportormardatabase=databases.Database("sqlite:///db.sqlite")metadata=sqlalchemy.MetaData()classDepartment(ormar.Model):classMeta:database=databasemetadata=metadataid:ormar.Integer(primary_key=True)name:ormar.String(max_length=100)classCourse(ormar.Model):classMeta:database=databasemetadata=metadataid:ormar.Integer(primary_key=True)name:ormar.String(max_length=100)completed:ormar.Boolean(default=False)department:ormar.ForeignKey(Department)department=Department(name='Science')# set up a relation with actual Model instancecourse=Course(name='Math',completed=False,department=department)# set up relation with only related model pk valuecourse2=Course(name='Math II',completed=False,department=department.pk)# set up a relation with dictionary corresponding to related modelcourse3=Course(name='Math III',completed=False,department=department.dict())# explicitly set up Nonecourse4=Course(name='Math III',completed=False,department=None)
None
Finally you can explicitly set it to None (default behavior if no value passed).
importdatabasesimportsqlalchemyimportormardatabase=databases.Database("sqlite:///db.sqlite")metadata=sqlalchemy.MetaData()classDepartment(ormar.Model):classMeta:database=databasemetadata=metadataid:ormar.Integer(primary_key=True)name:ormar.String(max_length=100)classCourse(ormar.Model):classMeta:database=databasemetadata=metadataid:ormar.Integer(primary_key=True)name:ormar.String(max_length=100)completed:ormar.Boolean(default=False)department:ormar.ForeignKey(Department)department=Department(name='Science')# set up a relation with actual Model instancecourse=Course(name='Math',completed=False,department=department)# set up relation with only related model pk valuecourse2=Course(name='Math II',completed=False,department=department.pk)# set up a relation with dictionary corresponding to related modelcourse3=Course(name='Math III',completed=False,department=department.dict())# explicitly set up Nonecourse4=Course(name='Math III',completed=False,department=None)
Warning
In all not None cases the primary key value for related model has to exist in database.
Otherwise an IntegrityError will be raised by your database driver library.
Many2Many
Many2Many(to, through) has required parameters to and through that takes target and relation Model classes.
Sqlalchemy column and Type are automatically taken from target Model.
Sqlalchemy column: class of a target Model primary key column
importdatabasesimportormarimportsqlalchemydatabase=databases.Database("sqlite:///db.sqlite")metadata=sqlalchemy.MetaData()classAuthor(ormar.Model):classMeta:tablename="authors"database=databasemetadata=metadataid:ormar.Integer(primary_key=True)first_name:ormar.String(max_length=80)last_name:ormar.String(max_length=80)classCategory(ormar.Model):classMeta:tablename="categories"database=databasemetadata=metadataid:ormar.Integer(primary_key=True)name:ormar.String(max_length=40)classPostCategory(ormar.Model):classMeta:tablename="posts_categories"database=databasemetadata=metadata# If there are no additional columns id will be created automatically as IntegerclassPost(ormar.Model):classMeta:tablename="posts"database=databasemetadata=metadataid:ormar.Integer(primary_key=True)title:ormar.String(max_length=200)categories:ormar.ManyToMany(Category,through=PostCategory)author:ormar.ForeignKey(Author)
# Add a category to a post.awaitpost.categories.add(news)# or from the other end:awaitnews.posts.add(post)
Warning
In all not None cases the primary key value for related model has to exist in database.
Otherwise an IntegrityError will be raised by your database driver library.
Creating new related Model instances
1
2
3
4
# Creating columns object from instance:awaitpost.categories.create(name="Tips")assertlen(awaitpost.categories.all())==2# newly created instance already have relation persisted in the database
Note
Note that when accessing QuerySet API methods through Many2Many relation you don't
need to use objects attribute like in normal queries.
To learn more about available QuerySet methods visit queries
Removing related models
1
2
3
4
# Removal of the relationship by oneawaitnews.posts.remove(post)# or all at onceawaitnews.posts.clear()
All other queryset methods
When access directly the related Many2Many field returns the list of related models.
But at the same time it exposes full QuerySet API, so you can filter, create, select related etc.
1
2
3
4
5
6
7
8
9
10
11
# Many to many relation exposes a list of columns models# and an API of the Queryset:assertnews==awaitpost.categories.get(name="News")# with all Queryset methods - filtering, selecting columns, counting etc.awaitnews.posts.filter(title__contains="M2M").all()awaitCategory.objects.filter(posts__author=guido).get()# columns models of many to many relation can be prefetchednews_posts=awaitnews.posts.select_related("author").all()assertnews_posts[0].author==guido
Tip
To learn more about available QuerySet methods visit queries