Model options and table metadata
In order not to pollute the model namespace, model-specific configuration isplaced in a special class called Meta (a convention borrowed from the djangoframework):
- from peewee import *
- contacts_db = SqliteDatabase('contacts.db')
- class Person(Model):
- name = CharField()
- class Meta:
- database = contacts_db
This instructs peewee that whenever a query is executed on Person to use thecontacts database.
Note
Take a look at the sample models - you will noticethat we created a BaseModel
that defined the database, and thenextended. This is the preferred way to define a database and create models.
Once the class is defined, you should not access ModelClass.Meta
, butinstead use ModelClass._meta
:
- >>> Person.Meta
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- AttributeError: type object 'Person' has no attribute 'Meta'
- >>> Person._meta
- <peewee.ModelOptions object at 0x7f51a2f03790>
The ModelOptions
class implements several methods which may be ofuse for retrieving model metadata (such as lists of fields, foreign keyrelationships, and more).
- >>> Person._meta.fields
- {'id': <peewee.AutoField object at 0x7f51a2e92750>,
- 'name': <peewee.CharField object at 0x7f51a2f0a510>}
- >>> Person._meta.primary_key
- <peewee.AutoField object at 0x7f51a2e92750>
- >>> Person._meta.database
- <peewee.SqliteDatabase object at 0x7f519bff6dd0>
There are several options you can specify as Meta
attributes. While mostoptions are inheritable, some are table-specific and will not be inherited bysubclasses.
Option | Meaning | Inheritable? |
---|---|---|
database | database for model | yes |
table_name | name of the table to store data | no |
table_function | function to generate table name dynamically | yes |
indexes | a list of fields to index | yes |
primary_key | a CompositeKey instance | yes |
constraints | a list of table constraints | yes |
schema | the database schema for the model | yes |
only_save_dirty | when calling model.save(), only save dirty fields | yes |
options | dictionary of options for create table extensions | yes |
table_settings | list of setting strings to go after close parentheses | yes |
temporary | indicate temporary table | yes |
legacy_table_names | use legacy table name generation (enabled by default) | yes |
depends_on | indicate this table depends on another for creation | no |
without_rowid | indicate table should not have rowid (SQLite only) | no |
Here is an example showing inheritable versus non-inheritable attributes:
- >>> db = SqliteDatabase(':memory:')
- >>> class ModelOne(Model):
- ... class Meta:
- ... database = db
- ... table_name = 'model_one_tbl'
- ...
- >>> class ModelTwo(ModelOne):
- ... pass
- ...
- >>> ModelOne._meta.database is ModelTwo._meta.database
- True
- >>> ModelOne._meta.table_name == ModelTwo._meta.table_name
- False
Meta.primary_key
The Meta.primarykey
attribute is used to specify either aCompositeKey
or to indicate that the model has _no primary key.Composite primary keys are discussed in more detail here: Composite primary keys.
To indicate that a model should not have a primary key, then set primary_key = False
.
Examples:
- class BlogToTag(Model):
- """A simple "through" table for many-to-many relationship."""
- blog = ForeignKeyField(Blog)
- tag = ForeignKeyField(Tag)
- class Meta:
- primary_key = CompositeKey('blog', 'tag')
- class NoPrimaryKey(Model):
- data = IntegerField()
- class Meta:
- primary_key = False
Table Names
By default Peewee will automatically generate a table name based on the name ofyour model class. The way the table-name is generated depends on the value ofMeta.legacy_table_names
. By default, legacy_table_names=True
so as toavoid breaking backwards-compatibility. However, if you wish to use the new andimproved table-name generation, you can specify legacy_table_names=False
.
This table shows the differences in how a model name is converted to a SQLtable name, depending on the value of legacy_table_names
:
Model name | legacy_table_names=True | legacy_table_names=False (new) |
---|---|---|
User | user | user |
UserProfile | userprofile | user_profile |
APIResponse | apiresponse | api_response |
WebHTTPRequest | webhttprequest | web_http_request |
mixedCamelCase | mixedcamelcase | mixed_camel_case |
Name2Numbers3XYZ | name2numbers3xyz | name2_numbers3_xyz |
Attention
To preserve backwards-compatibility, the current release (Peewee 3.x)specifies legacy_table_names=True
by default.
In the next major release (Peewee 4.0), legacy_table_names
will have adefault value of False
.
To explicitly specify the table name for a model class, use the table_name
Meta option. This feature can be useful for dealing with pre-existing databaseschemas that may have used awkward naming conventions:
- class UserProfile(Model):
- class Meta:
- table_name = 'user_profile_tbl'
If you wish to implement your own naming convention, you can specify thetable_function
Meta option. This function will be called with your modelclass and should return the desired table name as a string. Suppose our companyspecifies that table names should be lower-cased and end with “_tbl”, we canimplement this as a table function:
- def make_table_name(model_class):
- model_name = model_class.__name__
- return model_name.lower() + '_tbl'
- class BaseModel(Model):
- class Meta:
- table_function = make_table_name
- class User(BaseModel):
- # table_name will be "user_tbl".
- class UserProfile(BaseModel):
- # table_name will be "userprofile_tbl".