Sqlalchemy seeder that supports nested relationships.
Supported file types
Default installation
pip install sqlalchemyseed
When using yaml to loading entities from yaml files. Execute this command to install necessary dependencies
pip install sqlalchemyseed[yaml]
Required dependencies
- SQAlchemy>=1.4.0
Optional dependencies
- PyYAML>=5.4.0
# main.py
from sqlalchemyseed import load_entities_from_json, Seeder
from db import session
# load entities
entities = load_entities_from_json('tests/test_data.json')
# Initializing Seeder
seeder = Seeder() # or Seeder(session),
# Seeding
seeder.session = session # assign session if no session assigned before seeding
seeder.seed(entities)
# Committing
session.commit() # or seeder.session.commit()
Features & Options | Seeder | HybridSeeder |
---|---|---|
Support model and data keys |
✔️ | ✔️ |
Support model and filter keys |
❌ | ✔️ |
Optional argument add_to_session=False in the seed method |
✔️ | ❌ |
Assuming that Child(age=5)
exists in the database or session, then we should use filter instead of data, the
values of filter will query from the database or session, and assign it to the Parent.child
from sqlalchemyseed import HybridSeeder
from db import session
data = {
"model": "models.Parent",
"data": {
"!child": { # '!' is the reference prefix
"model": "models.Child",
"filter": {
"age": 5
}
}
}
}
# When seeding instances that has 'filter' key, then use HybridSeeder, otherwise use Seeder.
# ref_prefix can be changed according to your needs, defaults to '!'
seeder = HybridSeeder(session, ref_prefix='!')
seeder.seed(data)
session.commit() # or seeder.sesssion.commit()
In adding a reference attribute, add prefix ! or to the key in order to identify it. If you want '@' as prefix, you can just specify it to what seeder you use by adding ref_prefix='@' in the argument when instantiating the seeder in order for the seeder to identify the referencing attributes
If your class don't have a relationship attribute but instead a foreign key attribute you can use it the same as how you did it on a relationship attribute
from sqlalchemyseed import HybridSeeder
from db import session
instance = [
{
'model': 'tests.models.Company',
'data': {'name': 'MyCompany'}
},
{
'model': 'tests.models.Employee',
'data': [
{
'name': 'John Smith',
# foreign key attribute
'!company_id': {
'model': 'tests.models.Company', # models can be removed if it is a referencing attribute
'filter': {
'name': 'MyCompany'
}
}
},
{
'name': 'Juan Dela Cruz',
# relationship attribute
'!company': {
'model': 'tests.models.Company', # models can be removed if it is a referencing attribute
'filter': {
'name': 'MyCompany'
}
}
]
}
]
seeder = HybridSeeder(session)
seeder.seed(instance)
seeder.session.commit() # or session.commit()
// test_data.json
[
{
"model": "models.Person",
"data": {
"name": "You",
"age": 18
}
},
// when you have two or more objects of the same model, you can
{
"model": "models.Person",
"data": [
{
"name": "You",
"age": 18
},
{
"name": "Still You But Older",
"age": 40
}
]
}
]
// test_data.json
[
{
"model": "models.Person",
"data": {
"name": "John",
"age": 18,
// creates a job object
"!job": {
"model": "models.Job",
"data": {
"job_name": "Programmer",
}
}
}
},
// or this, if you want to add relationship that exists
// in your database use 'filter' instead of 'obj'
{
"model": "models.Person",
"data": {
"name": "Jeniffer",
"age": 18,
"!job": {
"model": "models.Job",
"filter": {
"job_name": "Programmer",
}
}
}
}
]
//test_data.json
[
{
"model": "models.Person",
"data": {
"name": "John",
"age": 18,
"!items": [
{
"model": "models.Item",
"data": {
"name": "Pencil"
}
},
{
"model": "models.Item",
"data": {
"name": "Eraser"
}
}
]
}
}
]
{
"model": "models.Parent",
"data": {
"name": "John Smith",
"!children": [
{
"model": "models.Child",
"data": {
"name": "Mark Smith",
"!children": [
{
"model": "models.GrandChild",
"data": {
"name": "Alice Smith"
}
}
]
}
}
]
}
}
data.json
{
"model": "models.Person",
"data": [
{
"name": "John March",
"age": 23
},
{
"name": "Juan Dela Cruz",
"age": 21
}
]
}
data.yml
model: models.Person
data:
- name: John March
age: 23
- name: Juan Dela Cruz
age: 21
data.csv
name, age
John March, 23
Juan Dela Cruz, 21
To load a csv file
load_entities_from_csv("data.csv", models.Person)
or
load_entities_from_csv("data.csv", "models.Person")
Note: Does not support relationships