Generic Model Layer for Python Web Applications using Sqlite3
To make the behavior of lazy_record avaliable, add the following into any files in which you define models:
import lazy_record
from lazy_record.associations import *
The first line makes lazy_record avaliable within your scope, and the second line makes the association decorators
has_many
, belongs_to
, and has_one
avaliable. You could neglect to add the second line, and instead use something like lazy_record.associations.has_many
.
Lazy Record Models inherit from lazy_record.Base
. Furthermore, they need to define the __attributes__
class variable to
reflect their database schema (it is assumed empty if not defined). An example schema and model is included below:
CREATE TABLE entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP NOT NULL
);
class Entry(lazy_record.Base):
__attributes__ = {
"name": str
}
Lazy Record exposes convience methods for querying records. Using the example above, you can do the following:
>>> entry = Entry(name="foo")
>>> entry.save()
>>> Entry.all()
<lazy_record.Query [Entry(id=1, name="foo", created_at=2016-01-08 01:53:45, updated_at=2016-01-08 01:53:45)]>
>>> Entry.where(name="bar")
<lazy_record.Query []>
>>> Entry.where("name LIKE ?", "bar")
<lazy_record.Query []>
Methods that return queries (where
, all
, joins
) can be chained, so something like this is valid:
Entry.where(name="foo").where(id=7)
Validations can be added by defining a __validates__
class variable to the model. This variable is a dictionary
whose keys are column names, and whose values are functions that return True
when the validation passes, and False
if the validation fails.
Some common validations can be found in lazy_record.validations
.
Example (validate name is all lowercase):
class Entry(lazy_record.Base):
__attributes__ = {
"name": str
}
__validates__ = {
"name": lambda record: record.name == record.name.lower()
}
Attempts to save an invalid record will raise lazy_record.RecordInvalid
.
The decorators @has_many
and @belongs_to
can be used to define relationships between records.
@belongs_to("post")
class Comment(lazy_record.Base):
...
@has_many("comments")
class Post(lazy_record.Base):
...
This allows the querying and creation of related records.
>>> post = Post()
>>> post.save()
>>> comment = post.comments.build()
>>> comment.save()
>>> post.comments
<lazy_record.Query [Comment(id=1, created_at=2016-01-08 01:53:45, updated_at=2016-01-08 01:53:45, post_id=1)]>
Currently, one-to-many and many-to-many relationships are supported, and the foreign keys can be changed for one-to-many
relationships. Many-to-many relationships require the creation of a joining table (and model), and to pass the keyword
through
to the @has_many
decorator that is the name of the joining table.
To connect lazy_record to a database, call lazy_record.connect_db
, passing the path to the database. The connection can
be closed by calling lazy_record.close_db()
.