Models provide a 1-to-1 mapping to database tables. Subclasses of Model declare any number of Field instances as class attributes. These fields correspond to columns on the table.
Table-level operations, such as select(), update(), insert(), and delete(), are implemented as classmethods. Row-level operations such as save() and delete_instance() are implemented as instancemethods.
Parameters: | kwargs – Initialize the model, assigning the given key/values to the appropriate fields. |
---|
Example:
class User(Model):
username = CharField()
join_date = DateTimeField(default=datetime.datetime.now)
is_admin = BooleanField()
u = User(username='charlie', is_admin=True)
Parameters: | selection – A list of model classes, field instances, functions or expressions. If no argument is provided, all columns for the given model will be selected. |
---|---|
Return type: | a SelectQuery for the given Model. |
Examples of selecting all columns (default):
User.select().where(User.active == True).order_by(User.username)
Example of selecting all columns on Tweet and the parent model, User. When the user foreign key is accessed on a Tweet instance no additional query will be needed (see N+1 for more details):
(Tweet
.select(Tweet, User)
.join(User)
.order_by(Tweet.created_date.desc()))
Parameters: | update – mapping of field-name to expression |
---|---|
Return type: | an UpdateQuery for the given Model |
Example showing users being marked inactive if their registration expired:
q = User.update(active=False).where(User.registration_expired == True)
q.execute() # Execute the query, updating the database.
Example showing an atomic update:
q = PageView.update(count=PageView.count + 1).where(PageView.url == url)
q.execute() # execute the query, updating the database.
Note
When an update query is executed, the number of rows modified will be returned.
Insert a new row into the database. If any fields on the model have default values, these values will be used if the fields are not explicitly set in the insert dictionary.
Parameters: | insert – mapping of field or field-name to expression. |
---|---|
Return type: | an InsertQuery for the given Model. |
Example showing creation of a new user:
q = User.insert(username='admin', active=True, registration_expired=False)
q.execute() # perform the insert.
You can also use Field objects as the keys:
User.insert(**{User.username: 'admin'}).execute()
If you have a model with a default value on one of the fields, and that field is not specified in the insert parameter, the default will be used:
class User(Model):
username = CharField()
active = BooleanField(default=True)
# This INSERT query will automatically specify `active=True`:
User.insert(username='charlie')
Note
When an insert query is executed on a table with an auto-incrementing primary key, the primary key of the new row will be returned.
Insert multiple rows at once. The rows parameter must be an iterable that yields dictionaries. As with insert(), fields that are not specified in the dictionary will use their default value, if one exists.
Note
Due to the nature of bulk inserts, each row must contain the same fields. The following will not work:
Person.insert_many([
{'first_name': 'Peewee', 'last_name': 'Herman'},
{'first_name': 'Huey'}, # Missing "last_name"!
])
Parameters: | rows – An iterable containing dictionaries of field-name-to-value. |
---|---|
Return type: | an InsertQuery for the given Model. |
Example of inserting multiple Users:
usernames = ['charlie', 'huey', 'peewee', 'mickey']
row_dicts = ({'username': username} for username in usernames)
# Insert 4 new rows.
User.insert_many(row_dicts).execute()
Because the rows parameter can be an arbitrary iterable, you can also use a generator:
def get_usernames():
for username in ['charlie', 'huey', 'peewee']:
yield {'username': username}
User.insert_many(get_usernames()).execute()
Insert rows into the table using a query as the data source. This API should be used for INSERT INTO...SELECT FROM queries.
Parameters: |
|
---|---|
Return type: | an InsertQuery for the given Model. |
Example of inserting data across tables for denormalization purposes:
source = (User
.select(User.username, fn.COUNT(Tweet.id))
.join(Tweet, JOIN_LEFT_OUTER)
.group_by(User.username))
UserTweetDenorm.insert_from(
[UserTweetDenorm.username, UserTweetDenorm.num_tweets],
source).execute()
Return type: | a DeleteQuery for the given Model. |
---|
Example showing the deletion of all inactive users:
q = User.delete().where(User.active == False)
q.execute() # remove the rows
Warning
This method performs a delete on the entire table. To delete a single instance, see Model.delete_instance().
Parameters: |
|
---|---|
Return type: | a RawQuery for the given Model |
Example selecting rows from the User table:
q = User.raw('select id, username from users')
for user in q:
print user.id, user.username
Note
Generally the use of raw is reserved for those cases where you can significantly optimize a select query. It is useful for select queries since it will return instances of the model.
Parameters: | attributes – key/value pairs of model attributes |
---|---|
Return type: | a model instance with the provided attributes |
Example showing the creation of a user (a row will be added to the database):
user = User.create(username='admin', password='test')
Note
The create() method is a shorthand for instantiate-then-save.
Parameters: | args – a list of query expressions, e.g. User.username == 'foo' |
---|---|
Return type: | Model instance or raises DoesNotExist exception |
Get a single row from the database that matches the given query. Raises a <model-class>.DoesNotExist if no rows are returned:
user = User.get(User.username == username, User.password == password)
This method is also exposed via the SelectQuery, though it takes no parameters:
active = User.select().where(User.active == True)
try:
user = active.where(
(User.username == username) &
(User.password == password)
).get()
except User.DoesNotExist:
user = None
Note
The get() method is shorthand for selecting with a limit of 1. It has the added behavior of raising an exception when no matching row is found. If more than one row is found, the first row returned by the database cursor will be used.
Return type: | ModelAlias instance |
---|
The alias() method is used to create self-joins.
Example:
Parent = Category.alias()
sq = (Category
.select(Category, Parent)
.join(Parent, on=(Category.parent == Parent.id))
.where(Parent.name == 'parent category'))
Note
When using a ModelAlias in a join, you must explicitly specify the join condition.
Parameters: | fail_silently (bool) – If set to True, the method will check for the existence of the table before attempting to create. |
---|
Create the table for the given model.
Example:
database.connect()
SomeModel.create_table() # Execute the create table query.
Parameters: |
|
---|
Drop the table for the given model.
Return type: | Boolean whether the table for this model exists in the database |
---|
Returns: | A list of queries required to create the table and indexes. |
---|
Parameters: |
|
---|
Save the given instance, creating or updating depending on whether it has a primary key. If force_insert=True an INSERT will be issued regardless of whether or not the primary key exists.
Example showing saving a model instance:
user = User()
user.username = 'some-user' # does not touch the database
user.save() # change is persisted to the db
Parameters: |
|
---|
Delete the given instance. Any foreign keys set to cascade on delete will be deleted automatically. For more programmatic control, you can call with recursive=True, which will delete any non-nullable related models (those that are nullable will be set to NULL). If you wish to delete all dependencies regardless of whether they are nullable, set delete_nullable=True.
example:
some_obj.delete_instance() # it is gone forever
Parameters: | search_nullable (bool) – Search models related via a nullable foreign key |
---|---|
Return type: | Generator expression yielding queries and foreign key fields |
Generate a list of queries of dependent models. Yields a 2-tuple containing the query and corresponding foreign key field. Useful for searching dependencies of a model, i.e. things that would be orphaned in the event of a delete.
Return a list of fields that were manually set.
Return type: | list |
---|
Note
If you just want to persist modified fields, you can call model.save(only=model.dirty_fields).
Return whether any fields were manually set.
Return type: | bool |
---|
This method provides a hook for performing model initialization after the row data has been populated.
The base class from which all other field types extend.
Parameters: |
|
---|
Attribute used to map this field to a column type, e.g. “string” or “datetime”
Boolean flag indicating if the field is attached to a model class.
The model the field belongs to. Only applies to bound fields.
The name of the field. Only applies to bound fields.
Parameters: | value – python data type to prep for storage in the database |
---|---|
Return type: | converted python datatype |
Parameters: | value – data coming from the backend storage |
---|---|
Return type: | python data type |
This method is a shorthand that is used, by default, by both db_value and python_value. You can usually get away with just implementing this.
Parameters: | value – arbitrary data from app or backend |
---|---|
Return type: | python data type |
Stores: integers
Stores: big integers
Stores: auto-incrementing integer fields suitable for use as primary key.
Stores: floating-point numbers
Stores: double-precision floating-point numbers
Stores: decimal numbers, using python standard library Decimal objects
Additional attributes and values:
max_digits | 10 |
decimal_places | 5 |
auto_round | False |
rounding | decimal.DefaultContext.rounding |
Stores: small strings (0-255 bytes)
Additional attributes and values:
max_length | 255 |
Stores: arbitrarily large strings
Stores: python datetime.datetime instances
Accepts a special parameter formats, which contains a list of formats the datetime can be encoded with. The default behavior is:
'%Y-%m-%d %H:%M:%S.%f' # year-month-day hour-minute-second.microsecond
'%Y-%m-%d %H:%M:%S' # year-month-day hour-minute-second
'%Y-%m-%d' # year-month-day
Note
If the incoming value does not match a format, it will be returned as-is
An expression suitable for extracting the year, for example to retrieve all blog posts from 2013:
Blog.select().where(Blog.pub_date.year == 2013)
An expression suitable for extracting the month from a stored date.
An expression suitable for extracting the day from a stored date.
An expression suitable for extracting the hour from a stored time.
An expression suitable for extracting the minute from a stored time.
An expression suitable for extracting the second from a stored time.
Stores: python datetime.date instances
Accepts a special parameter formats, which contains a list of formats the date can be encoded with. The default behavior is:
'%Y-%m-%d' # year-month-day
'%Y-%m-%d %H:%M:%S' # year-month-day hour-minute-second
'%Y-%m-%d %H:%M:%S.%f' # year-month-day hour-minute-second.microsecond
Note
If the incoming value does not match a format, it will be returned as-is
An expression suitable for extracting the year, for example to retrieve all people born in 1980:
Person.select().where(Person.dob.year == 1983)
Stores: python datetime.time instances
Accepts a special parameter formats, which contains a list of formats the time can be encoded with. The default behavior is:
'%H:%M:%S.%f' # hour:minute:second.microsecond
'%H:%M:%S' # hour:minute:second
'%H:%M' # hour:minute
'%Y-%m-%d %H:%M:%S.%f' # year-month-day hour-minute-second.microsecond
'%Y-%m-%d %H:%M:%S' # year-month-day hour-minute-second
Note
If the incoming value does not match a format, it will be returned as-is
Extract the hour from a time, for example to retreive all events occurring in the evening:
Event.select().where(Event.time.hour > 17)
Stores: True / False
Store arbitrary binary data.
Store UUID values. Currently only supported by PostgresqlDatabase.
Stores: relationship to another model
Parameters: |
|
---|
class User(Model):
name = CharField()
class Tweet(Model):
user = ForeignKeyField(User, related_name='tweets')
content = TextField()
# "user" attribute
>>> some_tweet.user
<User: charlie>
# "tweets" related name attribute
>>> for tweet in charlie.tweets:
... print tweet.content
Some tweet
Another tweet
Yet another tweet
Note
Foreign keys do not have a particular db_field as they will take their field type depending on the type of primary key on the model they are related to.
Note
If you manually specify a to_field, that field must be either a primary key or have a unique constraint.
Specify a composite primary key for a model. Unlike the other fields, a composite key is defined in the model’s Meta class after the fields have been defined. It takes as parameters the string names of the fields to use as the primary key:
class BlogTagThrough(Model):
blog = ForeignKeyField(Blog, related_name='tags')
tag = ForeignKeyField(Tag, related_name='blogs')
class Meta:
primary_key = CompositeKey('blog', 'tag')
The parent class from which all other query classes are drived. While you will not deal with Query directly in your code, it implements some methods that are common across all query types.
Parameters: | expressions – a list of one or more expressions |
---|---|
Return type: | a Query instance |
Example selection users where the username is equal to ‘somebody’:
sq = SelectQuery(User).where(User.username == 'somebody')
Example selecting tweets made by users who are either editors or administrators:
sq = SelectQuery(Tweet).join(User).where(
(User.is_editor == True) |
(User.is_admin == True))
Example of deleting tweets by users who are no longer active:
dq = DeleteQuery(Tweet).where(
Tweet.user << User.select().where(User.active == False))
dq.execute() # perform the delete query
Note
where() calls are chainable. Multiple calls will be “AND”-ed together.
Parameters: |
|
---|---|
Return type: | a Query instance |
Generate a JOIN clause from the current query context to the model passed in, and establishes model as the new query context.
Example selecting tweets and joining on user in order to restrict to only those tweets made by “admin” users:
sq = SelectQuery(Tweet).join(User).where(User.is_admin == True)
Example selecting users and joining on a particular foreign key field. See the example app for a real-life usage:
sq = SelectQuery(User).join(Relationship, on=Relationship.to_user)
Parameters: | model – model to switch the query context to. |
---|---|
Return type: | a clone of the query with a new query context |
Switches the query context to the given model. Raises an exception if the model has not been selected or joined on previously. Useful for performing multiple joins from a single table.
The following example selects from blog and joins on both entry and user:
sq = SelectQuery(Blog).join(Entry).switch(Blog).join(User)
Parameters: | alias (str) – A string to alias the result of this query |
---|---|
Return type: | a Query instance |
Assign an alias to given query, which can be used as part of a subquery.
Return type: | a 2-tuple containing the appropriate SQL query and a tuple of parameters |
---|
Execute the given query
Parameters: | as_tuple (bool) – return the row as a tuple or a single value |
---|---|
Return type: | the resulting row, either as a single value or tuple |
Provide a way to retrieve single values from select queries, for instance when performing an aggregation.
>>> PageView.select(fn.Count(fn.Distinct(PageView.url))).scalar()
100 # <-- there are 100 distinct URLs in the pageview table
By far the most complex of the query classes available in peewee. It supports all clauses commonly associated with select queries.
Methods on the select query can be chained together.
SelectQuery implements an __iter__() method, allowing it to be iterated to return model instances.
Parameters: |
|
---|
If no selection is provided, it will default to all the fields of the given model.
Example selecting some user instances from the database. Only the id and username columns are selected. When iterated, will return instances of the User model:
sq = SelectQuery(User, User.id, User.username)
for user in sq:
print user.username
Example selecting users and additionally the number of tweets made by the user. The User instances returned will have an additional attribute, ‘count’, that corresponds to the number of tweets made:
sq = (SelectQuery(
User, User, fn.Count(Tweet.id).alias('count'))
.join(Tweet)
.group_by(User))
Parameters: | selection – a list of expressions, which can be model classes or fields. if left blank, will default to all the fields of the given model. |
---|---|
Return type: | SelectQuery |
Note
Usually the selection will be specified when the instance is created. This method simply exists for the case when you want to modify the SELECT clause independent of instantiating a query.
query = User.select()
query = query.select(User.username)
Parameters: | args – one or more expressions, for example Model or SelectQuery instance(s). if left blank, will default to the table of the given model. |
---|---|
Return type: | SelectQuery |
# rather than a join, select from both tables and join with where.
query = User.select().from_(User, Blog).where(Blog.user == User.id)
Parameters: | clauses – a list of expressions, which can be model classes or individual field instances |
---|---|
Return type: | SelectQuery |
Group by one or more columns. If a model class is provided, all the fields on that model class will be used.
Example selecting users, joining on tweets, and grouping by the user so a count of tweets can be calculated for each user:
sq = (User
.select(User, fn.Count(Tweet.id).alias('count'))
.join(Tweet)
.group_by(User))
Parameters: | expressions – a list of one or more expressions |
---|---|
Return type: | SelectQuery |
Here is the above example selecting users and tweet counts, but restricting the results to those users who have created 100 or more tweets:
sq = (User
.select(User, fn.Count(Tweet.id).alias('count'))
.join(Tweet)
.group_by(User)
.having(fn.Count(Tweet.id) > 100))
Parameters: | clauses – a list of fields, calls to field.[asc|desc]() or one or more expressions |
---|---|
Return type: | SelectQuery |
Example of ordering users by username:
User.select().order_by(User.username)
Example of selecting tweets and ordering them first by user, then newest first:
Tweet.select().join(User).order_by(
User.username, Tweet.created_date.desc())
A more complex example ordering users by the number of tweets made (greatest to least), then ordered by username in the event of a tie:
tweet_ct = fn.Count(Tweet.id)
sq = (User
.select(User, tweet_ct.alias('count'))
.join(Tweet)
.group_by(User)
.order_by(tweet_ct.desc(), User.username))
Parameters: | windows (Window) – One or more Window instances. |
---|
Add one or more window definitions to this query.
window = Window(partition_by=[fn.date_trunc('day', PageView.timestamp)])
query = (PageView
.select(
PageView.url,
PageView.timestamp,
fn.Count(PageView.id).over(window=window))
.window(window)
.order_by(PageView.timestamp))
Parameters: | num (int) – limit results to num rows |
---|
Parameters: | num (int) – offset results by num rows |
---|
Parameters: |
|
---|---|
Return type: |
Shorthand for applying a LIMIT and OFFSET to the query.
Page indices are 1-based, so page 1 is the first page.
User.select().order_by(User.username).paginate(3, 20) # get users 41-60
Parameters: | is_distinct – See notes. |
---|---|
Return type: | SelectQuery |
Indicates that this query should only return distinct rows. Results in a SELECT DISTINCT query.
Note
The value for is_distinct should either be a boolean, in which case the query will (or won’t) be DISTINCT.
You can specify a list of one or more expressions to generate a DISTINCT ON query, e.g. .distinct([Model.col1, Model.col2]).
Return type: | SelectQuery |
---|
Indicate that this query should lock rows for update. If nowait is True then the database will raise an OperationalError if it cannot obtain the lock.
Return type: | SelectQuery |
---|
Flag this query indicating it should only attempt to reconstruct a single model instance for every row returned by the cursor. If multiple tables were queried, the columns returned are patched directly onto the single model instance.
Generally this method is useful for speeding up the time needed to construct model instances given a database cursor.
Note
this can provide a significant speed improvement when doing simple iteration over a large result set.
Return type: | iterable |
---|
By default peewee will cache rows returned by the cursor. This is to prevent things like multiple iterations, slicing and indexing from triggering extra queries. When you are iterating over a large number of rows, however, this cache can take up a lot of memory. Using iterator() will save memory by not storing all the returned model instances.
# iterate over large number of rows.
for obj in Stats.select().iterator():
# do something.
pass
Return type: | SelectQuery |
---|
Flag this query indicating it should simply return raw tuples from the cursor. This method is useful when you either do not want or do not need full model instances.
Return type: | SelectQuery |
---|
Flag this query indicating it should simply return dictionaries from the cursor. This method is useful when you either do not want or do not need full model instances.
Return type: | SelectQuery |
---|
This method provides one way to avoid the N+1 query problem.
Consider a webpage where you wish to display a list of users and all of their associated tweets. You could approach this problem by listing the users, then for each user executing a separate query to retrieve their tweets. This is the N+1 behavior, because the number of queries varies depending on the number of users. Conventional wisdom is that it is preferable to execute fewer queries. Peewee provides several ways to avoid this problem.
You can use the prefetch() helper, which uses IN clauses to retrieve the tweets for the listed users.
Another method is to select both the user and the tweet data in a single query, then de-dupe the users, aggregating the tweets in the process.
The raw column data might appear like this:
# user.id, user.username, tweet.id, tweet.user_id, tweet.message
[1, 'charlie', 1, 1, 'hello'],
[1, 'charlie', 2, 1, 'goodbye'],
[2, 'no-tweets', NULL, NULL, NULL],
[3, 'huey', 3, 3, 'meow'],
[3, 'huey', 4, 3, 'purr'],
[3, 'huey', 5, 3, 'hiss'],
We can infer from the JOIN clause that the user data will be duplicated, and therefore by de-duping the users, we can collect their tweets in one go and iterate over the users and tweets transparently.
query = (User
.select(User, Tweet)
.join(Tweet, JOIN_LEFT_OUTER)
.order_by(User.username, Tweet.id)
.aggregate_rows()) # .aggregate_rows() tells peewee to de-dupe the rows.
for user in query:
print user.username
for tweet in user.tweets:
print ' ', tweet.message
# Producing the following output:
charlie
hello
goodbye
huey
meow
purr
hiss
no-tweets
Warning
Be sure that you specify an ORDER BY clause that ensures duplicated data will appear in consecutive rows.
Note
You can specify arbitrarily complex joins, though for more complex queries it may be more efficient to use prefetch(). In short, try both and see what works best for your data-set.
Note
For more information, see the Avoiding N+1 queries document.
Parameters: |
|
---|---|
Return type: |
Annotate a query with an aggregation performed on a related model, for example, “get a list of users with the number of tweets for each”:
>>> User.select().annotate(Tweet)
If aggregation is None, it will default to fn.Count(related_model.id).alias('count') but can be anything:
>>> user_latest = User.select().annotate(Tweet, fn.Max(Tweet.created_date).alias('latest'))
Note
If the ForeignKeyField is nullable, then a LEFT OUTER join may need to be used:
User.select().join(Tweet, JOIN_LEFT_OUTER).annotate(Tweet)
Parameters: | aggregation – a function specifying what aggregation to perform, for example fn.Max(Tweet.created_date). |
---|
Method to look at an aggregate of rows using a given function and return a scalar value, such as the count of all rows or the average value of a particular column.
Parameters: | clear_limit (bool) – Remove any limit or offset clauses from the query before counting. |
---|---|
Return type: | an integer representing the number of rows in the current query |
Note
If the query has a GROUP BY, DISTINCT, LIMIT, or OFFSET clause, then the wrapped_count() method will be used instead.
>>> sq = SelectQuery(Tweet)
>>> sq.count()
45 # number of tweets
>>> deleted_tweets = sq.where(Tweet.status == DELETED)
>>> deleted_tweets.count()
3 # number of tweets that are marked as deleted
Parameters: | clear_limit (bool) – Remove any limit or offset clauses from the query before counting. |
---|---|
Return type: | an integer representing the number of rows in the current query |
Wrap the count query in a subquery. Additional overhead but will give correct counts when performing DISTINCT queries or those with GROUP BY clauses.
Note
count() will automatically default to wrapped_count() in the event the query is distinct or has a grouping.
Return type: | boolean whether the current query will return any rows. uses an optimized lookup, so use this rather than get(). |
---|
sq = User.select().where(User.active == True)
if sq.where(User.username == username, User.password == password).exists():
authenticated = True
Return type: | Model instance or raises DoesNotExist exception |
---|
Get a single row from the database that matches the given query. Raises a <model-class>.DoesNotExist if no rows are returned:
active = User.select().where(User.active == True)
try:
user = active.where(User.username == username).get()
except User.DoesNotExist:
user = None
This method is also exposed via the Model api, in which case it accepts arguments that are translated to the where clause:
user = User.get(User.active == True, User.username == username)
Return type: | Model instance or None if no results |
---|
Fetch the first row from a query. The result will be cached in case the entire query result-set should be iterated later.
Return type: | QueryResultWrapper |
---|
Executes the query and returns a QueryResultWrapper for iterating over the result set. The results are managed internally by the query and whenever a clause is added that would possibly alter the result set, the query is marked for re-execution.
Executes the query and returns populated model instances:
for user in User.select().where(User.active == True):
print user.username
Parameters: | value – Either an index or a slice object. |
---|
Return the model instance(s) at the requested indices. To get the first model, for instance:
query = User.select().order_by(User.username)
first_user = query[0]
first_five = query[:5]
Parameters: | rhs – Either a SelectQuery or a CompoundSelect |
---|---|
Return type: | CompoundSelect |
Create a UNION query with the right-hand object. The result will contain all values from both the left and right queries.
customers = Customer.select(Customer.city).where(Customer.state == 'KS')
stores = Store.select(Store.city).where(Store.state == 'KS')
# Get all cities in kansas where we have either a customer or a store.
all_cities = (customers | stores).order_by(SQL('city'))
Parameters: | rhs – Either a SelectQuery or a CompoundSelect |
---|---|
Return type: | CompoundSelect |
Create an INTERSECT query. The result will contain values that are in both the left and right queries.
customers = Customer.select(Customer.city).where(Customer.state == 'KS')
stores = Store.select(Store.city).where(Store.state == 'KS')
# Get all cities in kanasas where we have both customers and stores.
cities = (customers & stores).order_by(SQL('city'))
Parameters: | rhs – Either a SelectQuery or a CompoundSelect |
---|---|
Return type: | CompoundSelect |
Create an EXCEPT query. The result will contain values that are in the left-hand query but not in the right-hand query.
customers = Customer.select(Customer.city).where(Customer.state == 'KS')
stores = Store.select(Store.city).where(Store.state == 'KS')
# Get all cities in kanasas where we have customers but no stores.
cities = (customers - stores).order_by(SQL('city'))
Parameters: | rhs – Either a SelectQuery or a CompoundSelect |
---|---|
Return type: | CompoundSelect |
Create an symmetric difference query. The result will contain values that are in either the left-hand query or the right-hand query, but not both.
customers = Customer.select(Customer.city).where(Customer.state == 'KS')
stores = Store.select(Store.city).where(Store.state == 'KS')
# Get all cities in kanasas where we have either customers with no
# store, or a store with no customers.
cities = (customers ^ stores).order_by(SQL('city'))
Parameters: |
|
---|
Example in which users are marked inactive if their registration expired:
uq = UpdateQuery(User, active=False).where(User.registration_expired == True)
uq.execute() # Perform the actual update
Example of an atomic update:
atomic_update = UpdateQuery(PageCount, count = PageCount.count + 1).where(
PageCount.url == url)
atomic_update.execute() # will perform the actual update
Return type: | Number of rows updated |
---|
Performs the query
Creates an InsertQuery instance for the given model.
Parameters: |
|
---|
Basic example:
>>> fields = {'username': 'admin', 'password': 'test', 'active': True}
>>> iq = InsertQuery(User, fields)
>>> iq.execute() # insert new row and return primary key
2L
Example inserting multiple rows:
users = [
{'username': 'charlie', 'active': True},
{'username': 'peewee', 'active': False},
{'username': 'huey', 'active': True}]
iq = InsertQuery(User, rows=users)
iq.execute()
Example inserting using a query as the data source:
query = (User
.select(User.username, fn.COUNT(Tweet.id))
.join(Tweet, JOIN_LEFT_OUTER)
.group_by(User.username))
iq = InsertQuery(
UserTweetDenorm,
fields=[UserTweetDenorm.username, UserTweetDenorm.num_tweets],
query=query)
iq.execute()
Return type: | primary key of the new row |
---|
Performs the query
Perform an INSERT OR REPLACE query. Currently only Sqlite supports this method.
Creates a DELETE query for the given model.
Note
DeleteQuery will not traverse foreign keys or ensure that constraints are obeyed, so use it with care.
Example deleting users whose account is inactive:
dq = DeleteQuery(User).where(User.active == False)
Return type: | Number of rows deleted |
---|
Performs the query
Allows execution of an arbitrary query and returns instances of the model via a QueryResultsWrapper.
Note
Generally you will only need this for executing highly optimized SELECT queries.
Warning
If you are executing a parameterized query, you must use the correct interpolation string for your database. SQLite uses '?' and most others use '%s'.
Example selecting users with a given username:
>>> rq = RawQuery(User, 'SELECT * FROM users WHERE username = ?', 'admin')
>>> for obj in rq.execute():
... print obj
<User: admin>
Return type: | RawQuery |
---|
Flag this query indicating it should simply return raw tuples from the cursor. This method is useful when you either do not want or do not need full model instances.
Return type: | RawQuery |
---|
Flag this query indicating it should simply return raw dicts from the cursor. This method is useful when you either do not want or do not need full model instances.
Return type: | a QueryResultWrapper for iterating over the result set. The results are instances of the given model. |
---|
Performs the query
Compound select query.
Parameters: |
|
---|
Parameters: |
|
---|---|
Return type: | SelectQuery with related instances pre-populated |
Pre-fetch the appropriate instances from the subqueries and apply them to their corresponding parent row in the outer query. This function will eagerly load the related instances specified in the subqueries. This is a technique used to save doing O(n) queries for n rows, and rather is O(k) queries for k subqueries.
For example, consider you have a list of users and want to display all their tweets:
# let's impost some small restrictions on our queries
users = User.select().where(User.active == True)
tweets = Tweet.select().where(Tweet.published == True)
# this will perform 2 queries
users_pf = prefetch(users, tweets)
# now we can:
for user in users_pf:
print user.username
for tweet in user.tweets_prefetch:
print '- ', tweet.content
You can prefetch an arbitrary number of items. For instance, suppose we have a photo site, User -> Photo -> (Comments, Tags). That is, users can post photos, and these photos can have tags and comments on them. If we wanted to fetch a list of users, all their photos, and all the comments and tags on the photos:
users = User.select()
published_photos = Photo.select().where(Photo.published == True)
published_comments = Comment.select().where(
(Comment.is_spam == False) &
(Comment.num_flags < 3))
# note that we are just passing the Tag model -- it will be converted
# to a query automatically
users_pf = prefetch(users, published_photos, published_comments, Tag)
# now we can iterate users, photos, and comments/tags
for user in users_pf:
for photo in user.photo_set_prefetch:
for comment in photo.comment_set_prefetch:
# ...
for tag in photo.tag_set_prefetch:
# ...
Note
Subqueries must be related by foreign key and can be arbitrarily deep
Note
For more information, see the Avoiding N+1 queries document.
Warning
prefetch() can use up lots of RAM when the result set is large, and will not warn you if you are doing something dangerous, so it is up to you to know when to use it. Additionally, because of the semantics of subquerying, there may be some cases when prefetch does not act as you expect (for instnace, when applying a LIMIT to subqueries, but there may be others) – please report anything you think is a bug to github.
Parameters: |
|
---|
Note
if your database name is not known when the class is declared, you can pass None in as the database name which will mark the database as “deferred” and any attempt to connect while in this state will raise an exception. To initialize your database, call the Database.init() method with the database name
A high-level api for working with the supported database engines. Database provides a wrapper around some of the functions performed by the Adapter, in addition providing support for:
Whether to issue a commit after executing a select query. With some engines can prevent implicit transactions from piling up.
A class suitable for compiling queries
A mapping of field types to database column types, e.g. {'primary_key': 'SERIAL'}
Whether the given backend enforces foreign key constraints.
Whether the given backend supports selecting rows for update
The string used by the driver to interpolate query parameters
A mapping of operation codes to string operations, e.g. {OP_LIKE: 'LIKE BINARY'}
The string used by the driver to quote names
Table names that are reserved by the backend – if encountered in the application a warning will be issued.
Whether the given backend supports sequences
Whether the given backend supports deleting rows using a subquery that selects from the same table
If the database was instantiated with database=None, the database is said to be in a ‘deferred’ state (see notes) – if this is the case, you can initialize it at any time by calling the init method.
Parameters: |
|
---|
Establishes a connection to the database
Note
If you initialized with threadlocals=True, then this will store the connection inside a threadlocal, ensuring that connections are not shared across threads.
Closes the connection to the database (if one is open)
Note
If you initialized with threadlocals=True, only a connection local to the calling thread will be closed.
Return type: | a connection to the database, creates one if does not exist |
---|
Return type: | a cursor for executing queries |
---|
Parameters: |
|
---|---|
Return type: | the primary key of the most recently inserted instance |
Return type: | number of rows affected by the last query |
---|
Return type: | an instance of QueryCompiler using the field and op overrides specified. |
---|
Parameters: |
|
---|
Note
You can configure whether queries will automatically commit by using the set_autocommit() and Database.get_autocommit() methods.
Initiate a new transaction. By default not implemented as this is not part of the DB-API 2.0, but provided for API compatibility.
Call commit() on the active connection, committing the current transaction
Call rollback() on the active connection, rolling back the current transaction
Parameters: | autocommit – a boolean value indicating whether to turn on/off autocommit for the current connection |
---|
Return type: | a boolean value indicating whether autocommit is on for the current connection |
---|
Return type: | a list of table names in the database |
---|
Warning
Not implemented – implementations exist in subclasses
Parameters: | table – the name of table to introspect |
---|---|
Return type: | a list of (index_name, is_unique) tuples |
Warning
Not implemented – implementations exist in subclasses
Rtype boolean: |
---|
Warning
Not implemented – implementations exist in subclasses
Parameters: |
|
---|
Parameters: |
|
---|
Manually create a foreign key constraint using an ALTER TABLE query. This is primarily used when creating a circular foreign key dependency, for example:
PostProxy = Proxy()
class User(Model):
username = CharField()
favorite_post = ForeignKeyField(PostProxy, null=True)
class Post(Model):
title = CharField()
author = ForeignKeyField(User, related_name='posts')
PostProxy.initialize(Post)
# Create tables. The foreign key from Post -> User will be created
# automatically, but the foreign key from User -> Post must be added
# manually.
User.create_table()
Post.create_table()
# Manually add the foreign key constraint on `User`, since we could
# not add it until we had created the `Post` table.
db.create_foreign_key(User, User.favorite_post)
Parameters: | sequence_name – name of sequence to create |
---|
Note
only works with database engines that support sequences
Parameters: |
|
---|
Parameters: | sequence_name – name of sequence to drop |
---|
Note
only works with database engines that support sequences
Parameters: |
|
---|
This method should be used for creating tables as it will resolve the model dependency graph and ensure the tables are created in the correct order.
Usage:
db.create_tables([User, Tweet, Something], safe=True)
Parameters: |
|
---|
This method should be used for dropping tables, as it will resolve the model dependency graph and ensure the tables are dropped in the correct order.
Usage:
db.drop_tables([User, Tweet, Something], safe=True)
Return a context manager that executes statements in a transaction. If an error is raised inside the context manager, the transaction will be rolled back, otherwise statements are committed when exiting.
# delete a blog instance and all its associated entries, but
# do so within a transaction
with database.transaction():
blog.delete_instance(recursive=True)
Decorator that wraps the given function in a single transaction, which, upon success will be committed. If an error is raised inside the function, the transaction will be rolled back and the error will be re-raised.
Nested functions can be wrapped with commit_on_success - the database will keep a stack and only commit when it reaches the end of the outermost function.
Parameters: | func – function to decorate |
---|
@database.commit_on_success
def transfer_money(from_acct, to_acct, amt):
from_acct.charge(amt)
to_acct.pay(amt)
return amt
Return a context manager that executes statements in a savepoint. If an error is raised inside the context manager, the savepoint will be rolled back, otherwise statements are committed when exiting.
Savepoints can be thought of as nested transactions.
Parameters: | sid (str) – A string identifier for the savepoint. |
---|
Register a mapping of field overrides for the database class. Used to register custom fields or override the defaults.
Parameters: | fields (dict) – A mapping of db_field to column type |
---|
Register a mapping of operations understood by the QueryCompiler to their SQL equivalent, e.g. {OP_EQ: '='}. Used to extend the types of field comparisons.
Parameters: | fields (dict) – A mapping of db_field to column type |
---|
Return an expression suitable for extracting a date part from a date field. For instance, extract the year from a DateTimeField.
Parameters: |
|
---|---|
Return type: | an expression object. |
This hook is called when an error is raised executing a query, allowing your application to inject custom error handling behavior. The default implementation simply reraises the exception.
class SqliteDatabaseCustom(SqliteDatabase):
def sql_error_handler(self, exception, sql, params, require_commit):
# Perform some custom behavior, for example close the
# connection to the database.
self.close()
# Re-raise the exception.
raise exception
Database subclass that works with the “sqlite3” driver. In addition to the default database parameters, SqliteDatabase also accepts a journal_mode parameter which will configure the journaling mode.
To use write-ahead log and connection-per-thread:
db = SqliteDatabase('my_app.db', threadlocals=True, journal_mode='WAL')
A helper class that will convert arbitrary function calls to SQL function calls.
To express functions in peewee, use the fn object. The way it works is anything to the right of the “dot” operator will be treated as a function. You can pass that function arbitrary parameters which can be other valid expressions.
For example:
Peewee expression | Equivalent SQL |
---|---|
fn.Count(Tweet.id).alias('count') | Count(t1."id") AS count |
fn.Lower(fn.Substr(User.username, 1, 1)) | Lower(Substr(t1."username", 1, 1)) |
fn.Rand().alias('random') | Rand() AS random |
fn.Stddev(Employee.salary).alias('sdv') | Stddev(t1."salary") AS sdv |
Basic support for SQL window functions.
Parameters: |
---|
Examples:
# Get the list of employees and the average salary for their dept.
query = (Employee
.select(
Employee.name,
Employee.department,
Employee.salary,
fn.Avg(Employee.salary).over(
partition_by=[Employee.department]))
.order_by(Employee.name))
# Rank employees by salary.
query = (Employee
.select(
Employee.name,
Employee.salary,
fn.rank().over(
order_by=[Employee.salary])))
# Get a list of page-views, along with avg pageviews for that day.
query = (PageView
.select(
PageView.url,
PageView.timestamp,
fn.Count(PageView.id).over(
partition_by=[fn.date_trunc(
'day', PageView.timestamp)]))
.order_by(PageView.timestamp))
# Same as above but using a window class.
window = Window(partition_by=[fn.date_trunc('day', PageView.timestamp)])
query = (PageView
.select(
PageView.url,
PageView.timestamp,
fn.Count(PageView.id).over(window=window))
.window(window) # Need to include our Window here.
.order_by(PageView.timestamp))
Add fragments of SQL to a peewee query. For example you might want to reference an aliased name.
Parameters: |
|
---|
# Retrieve user table and "annotate" it with a count of tweets for each
# user.
query = (User
.select(User, fn.Count(Tweet.id).alias('ct'))
.join(Tweet, JOIN_LEFT_OUTER)
.group_by(User))
# Sort the users by number of tweets.
query = query.order_by(SQL('ct DESC'))
Create a WINDOW definition.
Parameters: |
---|
Examples:
# Get the list of employees and the average salary for their dept.
window = Window(partition_by=[Employee.department]).alias('dept_w')
query = (Employee
.select(
Employee.name,
Employee.department,
Employee.salary,
fn.Avg(Employee.salary).over(window))
.window(window)
.order_by(Employee.name))
Proxy class useful for situations when you wish to defer the initialization of an object. For instance, you want to define your models but you do not know what database engine you will be using until runtime.
Example:
database_proxy = Proxy() # Create a proxy for our db. class BaseModel(Model): class Meta: database = database_proxy # Use proxy for our DB. class User(BaseModel): username = CharField() # Based on configuration, use a different database. if app.config['DEBUG']: database = SqliteDatabase('local.db') elif app.config['TESTING']: database = SqliteDatabase(':memory:') else: database = PostgresqlDatabase('mega_production_db') # Configure our proxy to use the db we specified in config. database_proxy.initialize(database)
The Node class is the parent class for all composable parts of a query, and forms the basis of peewee’s expression API. The following classes extend Node:
Overridden operators:
Create a binary expression using case-insensitive string search.
Create a binary expression using case-insensitive prefix search.
Create a binary expression using case-insensitive suffix search.
Create an expression that will match values between low and high.
Match based on regular expression.
Concatenate the current node with the provided rhs.
Negate the node. This translates roughly into NOT (<node>).
Apply an alias to the given node. This translates into <node> AS <name>.
Apply ascending ordering to the given node. This translates into <node> ASC.
Apply descending ordering to the given node. This translates into <node> DESC.