Fields¶
The Field
class is used to describe the mapping of Model
attributes to database columns. Each field type has a corresponding SQL storage
class (i.e. varchar, int), and conversion between python data types and underlying
storage is handled transparently.
When creating a Model
class, fields are defined as class-level attributes.
This should look familiar to users of the django framework. Here’s an example:
from peewee import *
class User(Model):
username = CharField()
join_date = DateTimeField()
about_me = TextField()
There is one special type of field, ForeignKeyField
, which allows you
to expose foreign-key relationships between models in an intuitive way:
class Message(Model):
user = ForeignKeyField(User, related_name='messages')
body = TextField()
send_date = DateTimeField()
This allows you to write code like the following:
>>> print some_message.user.username
Some User
>>> for message in some_user.messages:
... print message.body
some message
another message
yet another message
Field types table¶
Parameters accepted by all field types and their default values:
null = False
– boolean indicating whether null values are allowed to be storeddb_index = False
– boolean indicating whether to create an index on this columnunique = False
– boolean indicating whether to create a unique index on this columnverbose_name = None
– string representing the “user-friendly” name of this fieldhelp_text = None
– string representing any helpful text for this fielddb_column = None
– string representing the underlying column to use if different, useful for legacy databases
Field Type | Sqlite | Postgresql | MySQL |
---|---|---|---|
CharField |
varchar | varchar | varchar |
TextField |
text | text | longtext |
DateTimeField |
datetime | timestamp | datetime |
IntegerField |
integer | integer | integer |
BooleanField |
smallint | boolean | bool |
FloatField |
real | real | real |
DoubleField |
real | double precision | double precision |
BigIntegerField |
integer | bigint | bigint |
DecimalField |
decimal | numeric | numeric |
PrimaryKeyField |
integer | serial | integer |
ForeignKeyField |
integer | integer | integer |
DateField |
date | date | date |
TimeField |
time | time | time |
Some fields take special parameters...¶
Field type | Special Parameters |
---|---|
CharField |
max_length |
DateTimeField |
formats |
DateField |
formats |
TimeField |
formats |
DecimalField |
|
ForeignKeyField |
to , related_name ,
cascade , extra |
Self-referential Foreign Keys¶
Since the class is not available at the time the field is declared, when creating a self-referential foreign key pass in ‘self’ as the “to” relation:
class Category(Model):
name = CharField()
parent = ForeignKeyField('self', related_name='children', null=True)
Implementing Many to Many¶
Peewee does not provide a “field” for many to many relationships the way that django does – this is because the “field” really is hiding an intermediary table. To implement many-to-many with peewee, you will therefore create the intermediary table yourself and query through it:
class Student(Model):
name = CharField()
class Course(Model):
name = CharField()
class StudentCourse(Model):
student = ForeignKeyField(Student)
course = ForeignKeyField(Course)
To query, let’s say we want to find students who are enrolled in math class:
for student in Student.select().join(StudentCourse).join(Course).where(name='math'):
print student.name
You could also express this as:
for student in Student.filter(studentcourse_set__course__name='math'):
print student.name
To query what classes a given student is enrolled in:
for course in Course.select().join(StudentCourse).join(Student).where(name='da vinci'):
print course.name
# or, similarly
for course in Course.filter(studentcourse_set__student__name='da vinci'):
print course.name
Field class API¶
-
class
Field
¶ The base class from which all other field types extend.
-
__init__
(null=False, db_index=False, unique=False, verbose_name=None, help_text=None, *args, **kwargs)¶ Parameters: - null – this column can accept
None
orNULL
values - db_index – create an index for this column when creating the table
- unique – create a unique index for this column when creating the table
- verbose_name – specify a “verbose name” for this field, useful for metadata purposes
- help_text – specify some instruction text for the usage/meaning of this field
- null – this column can accept
-
db_value
(value)¶ Parameters: value – python data type to prep for storage in the database Return type: converted python datatype
-
python_value
(value)¶ Parameters: value – data coming from the backend storage Return type: python data type
-
lookup_value
(lookup_type, value)¶ Parameters: - lookup_type – a peewee lookup type, such as ‘eq’ or ‘contains’
- value – a python data type
Return type: data type converted for use when querying
-
-
class
CharField
¶ Stores: small strings (0-255 bytes)
-
class
TextField
¶ Stores: arbitrarily large strings
-
class
DateTimeField
¶ Stores: python
datetime.datetime
instancesAccepts 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
-
class
DateField
¶ Stores: python
datetime.date
instancesAccepts 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
-
class
TimeField
¶ Stores: python
datetime.time
instancesAccepts 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
-
class
IntegerField
¶ Stores: integers
-
class
BooleanField
¶ Stores:
True
/False
-
class
FloatField
¶ Stores: floating-point numbers
-
class
DecimalField
¶ Stores: decimal numbers
It’s default behavior is to return
decimal.Decimal
Python object. This is can store really large numbers so Python does not support seamless conversion from Decimal to float.If the only reason for you to use Decimal at database is to store amount where it always has exactly two decimal places and you happen then it might be easier for you to turn on
auto_round
andalways_float
flags.The former will make sure that if the value has higher precision than the number of
decimal_places
then it round it to that value before send that to database. This will save from some unexpected “Data truncation” warnings from MySQL backend (.. _ref: http://bit.ly/bWr1mn).The latter will make sure that in Python code you always get the value as
float
instead ofDecimal
. This way you can easily mix other float numbers without tracking their types. Alsofloat
can be faster thanDecimal
.
-
class
PrimaryKeyField
¶ Stores: auto-incrementing integer fields suitable for use as primary key
-
class
ForeignKeyField
¶ Stores: relationship to another model
-
__init__
(to[, related_name=None[, ...]])¶ Parameters: - to – related
Model
class or the string ‘self’ if declaring a self-referential foreign key - related_name – attribute to expose on related model
class Blog(Model): name = CharField() class Entry(Model): blog = ForeignKeyField(Blog, related_name='entries') title = CharField() content = TextField() # "blog" attribute >>> some_entry.blog <Blog: My Awesome Blog> # "entries" related name attribute >>> for entry in my_awesome_blog.entries: ... print entry.title Some entry Another entry Yet another entry
- to – related
-