Package: jardin
Jardin is apandas.DataFrame-based ORM for Python applications.Getting startedIn your working directory (the root of your app), create a file namedjardin_conf.py:# jardin_conf.pyDATABASES={'my_first_database':'https://username:password@database.url:port','my_second_database':'https://username:password@database.url:port'}LOG_LEVEL=logging.DEBUGWATERMARK='My Great App'Then, in your app, say you have a table calledusers:# app.pyimportjardinclassUser(jardin.Model):db_names={'read':'my_first_database','write':'my_second_database'}In the console:>>>fromappimportUsers>>>users=User.last(4)# /* My Great App */ SELECT * FROM users ORDER BY u.created_at DESC LIMIT 4;>>>usersidnameemail...0Johnjohn@beatl.es...1Paulpaul@beatl.es...2Georgegeorge@beatl.es...3Ringoringo@beatl.es...The resulting object is a pandas dataframe:>>>importpandas>>>isinstance(users,pandas.DataFrame)True>>>isinstance(users,jardin.Collection)TrueQueriesSELECT queriesHere is the basic syntax to select records from the database>>>users=User.select(select=['id','name'],where={'email':'paul@beatl.es'},order='id ASC',limit=1)# /* My Great App */ SELECT u.id, u.name FROM users u WHERE u.email = 'paul@beatl.es' ORDER BY u.id ASC LIMIT 1;>>>usersidname1PaulArgumentsselect– The list of columns to return. If not provided, all
columns will be returned.where– conditions. Many different formats can be used to provide
conditions. Seedocs.inner_join,left_join– List of tables to join with their
join condition. Can also be a list of classes if the appropriate
associations have been declared. Seedocs.order– order clauselimit– limit clausegroup– grouping clausescopes– list of pre-defined scopes. See docs.whereargumentHere are the different ways to feed a condition clause to a query. *where = "name = 'John'"*where = {'name': 'John'}*where = {'id': (0, 3)}– selects whereidis between 0 and 3 *where = {'id': [0, 1, 2]}– selects whereidis in the array *where =[{'id':(0, 10), 'instrument':'drums'},["created_at > %(created_at)s", {'created_at':'1963-03-22'}]]inner_join,left_joinargumentsThe simplest way to join another table is as follows>>>User.select(inner_join=["instruments i ON i.id = u.instrument_id"])If you have configured your models associations, seehere, you can simply pass the class as argument:>>>User.select(inner_join=[Instruments])Individual record selectionYou can also look-up a single record by id:>>>User.find(1)# /* My Great App */ SELECT * FROM users u WHERE u.id = 1;{'id':1,'name':'Paul','email':'paul@beatl.es',...}Note that the returned object is aRecordobject which allows you to
access attributes in those way:>>>user['name']Paul>>>user.namePaulINSERT queries>>>user=User.insert(name='Pete',email='pete@beatl.es')# /* My Great App */ INSERT INTO users (name, email) VALUES ('Pete', 'pete@beatl.es') RETURNING id;# /* My Great App */ SELECT u.* FROM users WHERE u.id = 4;>>>useridnameemail4Petepete@beatl.esUPDATE queries>>>users=User.update(values={'hair':'long'},where={'name':'John'})# /* My Great App */ UPDATE users u SET (u.hair) = ('long') WHERE u.name = 'John' RETURNING id;# /* My Great App */ SELECT * FROM users u WHERE u.name = 'John';DELETE queries>>>User.delete(where={'id':1})# /* My Great App */ DELETE FROM users u WHERE u.id = 1;AssociationsIt is possible to define associations between models. For example, if
each user has multiple instruments:# app.pyimportjardinclassMyModel(jardin.Model):db_names={'read':'my_first_database','write':'my_second_database'}classInstrument(MyModel):belongs_to={'users':'user_id'}classUser(MyModel):has_many=[Instruments]and then you can query the associated records:>>>users=User.select()# /* My Great App */ SELECT * FROM users u;>>>instruments=users.instruments()# /* My Great App */ SELECT * FROM instruments i WHERE i.id IN (0, 1, ...);Or you can declare joins more easily>>>users=User.select(inner_join=[Instruments])ScopesQueries conditions can be generalized across your app:# app.pyclassUser(jardin.Model):scopes={'alive':{'name':['Paul','Ringo']},'guitarists':{'name':['John','George']}}The key is the name of the scope, and the value is the conditions to be
applied. Anything that can be fed to thewhereargument ofModel#selectcan be used to define a scope.Use them as such:>>>users=User.select(scopes=['alive'],...)# /* My Great App */ SELECT * FROM users u WHERE u.name IN ('Paul', 'Ringo') AND ...;MiscCachingJardin implements a LRU caching mechanism for thejardin.querymethod.SetupTo confgure, add injardin_conf.py.# jardin_conf.py# to configure cache methods:CACHE={'methods':{'disk':{'dir':<pathtocachedirectory>,# default to `/tmp/jardin_cache`'limit':100000,# maximum size in bytes of cached files. when size of cache is above limit, files are deleted based on LRU # default to None},'s3':{'bucket_name':<bucketname>,'path':<path>,# subfolder path where all cached files will be placed'delete_expired_files':False# default is False}},'method':<defaultmethod># default to None}Methods supporteddisk (files saved infeatherformat)S3memcached (coming soon)UsageThen, you can use it with:>>>df=jardin.query(sql,params,db="jardin_db",cache=True,ttl=10,cache_method="s3")Watermark and traceMultiple databases