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):

  1. from peewee import *
  2.  
  3. contacts_db = SqliteDatabase('contacts.db')
  4.  
  5. class Person(Model):
  6. name = CharField()
  7.  
  8. class Meta:
  9. 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:

  1. >>> Person.Meta
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. AttributeError: type object 'Person' has no attribute 'Meta'
  5.  
  6. >>> Person._meta
  7. <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).

  1. >>> Person._meta.fields
  2. {'id': <peewee.AutoField object at 0x7f51a2e92750>,
  3. 'name': <peewee.CharField object at 0x7f51a2f0a510>}
  4.  
  5. >>> Person._meta.primary_key
  6. <peewee.AutoField object at 0x7f51a2e92750>
  7.  
  8. >>> Person._meta.database
  9. <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.

OptionMeaningInheritable?
databasedatabase for modelyes
table_namename of the table to store datano
table_functionfunction to generate table name dynamicallyyes
indexesa list of fields to indexyes
primary_keya CompositeKey instanceyes
constraintsa list of table constraintsyes
schemathe database schema for the modelyes
only_save_dirtywhen calling model.save(), only save dirty fieldsyes
optionsdictionary of options for create table extensionsyes
table_settingslist of setting strings to go after close parenthesesyes
temporaryindicate temporary tableyes
legacy_table_namesuse legacy table name generation (enabled by default)yes
depends_onindicate this table depends on another for creationno
without_rowidindicate table should not have rowid (SQLite only)no

Here is an example showing inheritable versus non-inheritable attributes:

  1. >>> db = SqliteDatabase(':memory:')
  2. >>> class ModelOne(Model):
  3. ... class Meta:
  4. ... database = db
  5. ... table_name = 'model_one_tbl'
  6. ...
  7. >>> class ModelTwo(ModelOne):
  8. ... pass
  9. ...
  10. >>> ModelOne._meta.database is ModelTwo._meta.database
  11. True
  12. >>> ModelOne._meta.table_name == ModelTwo._meta.table_name
  13. 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:

  1. class BlogToTag(Model):
  2. """A simple "through" table for many-to-many relationship."""
  3. blog = ForeignKeyField(Blog)
  4. tag = ForeignKeyField(Tag)
  5.  
  6. class Meta:
  7. primary_key = CompositeKey('blog', 'tag')
  8.  
  9. class NoPrimaryKey(Model):
  10. data = IntegerField()
  11.  
  12. class Meta:
  13. 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 namelegacy_table_names=Truelegacy_table_names=False (new)
Useruseruser
UserProfileuserprofileuser_profile
APIResponseapiresponseapi_response
WebHTTPRequestwebhttprequestweb_http_request
mixedCamelCasemixedcamelcasemixed_camel_case
Name2Numbers3XYZname2numbers3xyzname2_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_nameMeta option. This feature can be useful for dealing with pre-existing databaseschemas that may have used awkward naming conventions:

  1. class UserProfile(Model):
  2. class Meta:
  3. 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:

  1. def make_table_name(model_class):
  2. model_name = model_class.__name__
  3. return model_name.lower() + '_tbl'
  4.  
  5. class BaseModel(Model):
  6. class Meta:
  7. table_function = make_table_name
  8.  
  9. class User(BaseModel):
  10. # table_name will be "user_tbl".
  11.  
  12. class UserProfile(BaseModel):
  13. # table_name will be "userprofile_tbl".