📜 ⬆️ ⬇️

Peewee - easy, flexible and very fast ORM in Python

image

I suggest that all dzhangistam / alchemists respond a little and read a free interpretation of the introductory tutorial and part of the documentation on Peewee - stand-alone ORM, which is mandatory for any python artist and, in particular, a flysker. They write about her a little, but in vain. It is very easy to make friends with Peewee, especially if you are already familiar with any ORM on ActiveRecord. More importantly, it's nice to be friends with her :) Well, let's begin.


Installation
With pip:
pip install peewee 

')
From the repository:
 git clone https://github.com/coleifer/peewee.git cd peewee python setup.py install 


Tests:
 python setup.py test 


There is a harness for flask:
 pip install flask-peewee 



Defining models or “smacks of janga”


All of the following code can be repeated one by one in the interactive interpreter or a separate script.

 from peewee import * db = SqliteDatabase('people.db') class Person(Model): name = CharField() birthday = DateField() is_relative = BooleanField() class Meta: database = db #      'people.db' 


There are many types of fields for all occasions . Peewee takes on the conversion of Python objects into values ​​suitable for the database, and vice versa.

Initial arguments


Each field accepts the following initialization arguments:


Metadata


For each table, you can write a single metadata in class Meta :

OptionDescriptionInherited?
databasemodel databaseYes
db_tablethe name of the table in which the data will be storednot
indexeslist of fields to indexYes
order_bythe list of fields to sort by defaultYes
primary_keycomposite primary key, instance of the CompositeKey class, exampleYes
table_aliasalias tables for use in queriesnot


Let's try to set relationships between models through a foreign key. With peewee, it's simple:

 class Pet(Model): owner = ForeignKeyField(Person, related_name='pets') name = CharField() animal_type = CharField() class Meta: database = db #      'people.db' 


The models are described, it remains to create for them the corresponding tables in the database:

 >>> Person.create_table() >>> Pet.create_table() 


Work with data


For example, create a few people and get them pets:

 >>> from datetime import date >>> uncle_bob = Person(name='Bob', birthday=date(1960, 1, 15), is_relative=True) >>> uncle_bob.save() # c     


Records can be created directly using the Model.create () method without the explicit save ():

 >>> grandma = Person.create(name='Grandma', birthday=date(1935, 3, 1), is_relative=True) >>> herb = Person.create(name='Herb', birthday=date(1950, 5, 5), is_relative=False) 


We will please granny with the surname:

 >>> grandma.name = 'Grandma L.' >>> grandma.save() #   grandma 


Now we will generate some living creatures. Granny is allergic to cats, but the coat of arms has some problems :

 >>> bob_kitty = Pet.create(owner=uncle_bob, name='Kitty', animal_type='cat') >>> herb_fido = Pet.create(owner=herb, name='Fido', animal_type='dog') >>> herb_mittens = Pet.create(owner=herb, name='Mittens', animal_type='cat') >>> herb_mittens_jr = Pet.create(owner=herb, name='Mittens Jr', animal_type='cat') 


At some point, Mitten tired of living with the Coat of Arms, and taking advantage of the open window, he proudly ran into the sunset. Respecting his right to personal liberty, we will delete the corresponding entry from the database:

 >>> herb_mittens.delete_instance() # ,  1 


As you can see, the delete operation returns the number of deleted records, in this case, 1.

Uncle Bob decided that the coat of arms had so many animals and had Fido pressed him:

 >>> herb_fido.owner = uncle_bob >>> herb_fido.save() >>> bob_fido = herb_fido #        


Samples


Samples are made directly with the class object and return SelectQuery instances (analogue of the QuerySet in jung).

Extract one record


To retrieve a single entry, use the SelectQuery.get() method:

 >>> grandma = Person.select().where(Person.name == 'Grandma L.').get() 


You can shorten the request by substituting the argument directly in get() :

 >>> grandma = Person.get(Person.name == 'Grandma L.') 


Extract multiple entries


Let's go through all the instances of Person loop:

 >>> for person in Person.select(): ... print person.name, person.is_relative ... Bob True Grandma L. True Herb False 


Go through the Person instances and all the related records:

 >>> for person in Person.select(): ... print person.name, person.pets.count(), 'pets' ... for pet in person.pets: ... print ' ', pet.name, pet.animal_type ... Bob 2 pets Kitty cat Fido dog Grandma L. 0 pets Herb 1 pets Mittens Jr cat 


We catch all the cats and their owners of people (or vice versa?):

 >>> for pet in Pet.select().where(Pet.animal_type == 'cat'): ... print pet.name, pet.owner.name ... Kitty Bob Mittens Jr Herb 


Not without join'ov:

 #     >>> for pet in Pet.select().join(Person).where(Person.name == 'Bob'): ... print pet.name ... Kitty Fido 


You can extract the same selection in a different way - by explicitly passing the object with Bob to the query:

 >>> for pet in Pet.select().where(Pet.owner == uncle_bob): ... print pet.name 


Sort the sample in alphabetical order. To do this, we use the SelectQuery.order_by() method:

 >>> for pet in Pet.select().where(Pet.owner == uncle_bob).order_by(Pet.name): ... print pet.name ... Fido Kitty 


Sort people by age:

 >>> for person in Person.select().order_by(Person.birthday.desc()): ... print person.name ... Bob Herb Grandma L. 


Let's try a more complex query. Choose all people born


 >>> d1940 = date(1940, 1, 1) >>> d1960 = date(1960, 1, 1) >>> for person in Person.select().where((Person.birthday < d1940) | (Person.birthday > d1960)): ... print person.name ... Bob Grandma L. 


Hint
The where((Person.birthday < d1940) | (Person.birthday > d1960)) can also be written as where(Person.birthday < d1940 or Person.birthday > d1960) , but it is better not to do this, since A peewee does not always correctly handle such an entry.


And now torobane. Choose those born between 1940 and 1960:

 >>> for person in Person.select().where((Person.birthday > d1940) & (Person.birthday < d1960)): ... print person.name ... Herb 


And one last thing. Let's use the SQL function and select all people whose name starts with a “G” in any case:

 >>> for person in Person.select().where(fn.Lower(fn.Substr(Person.name, 1, 1)) == 'g'): ... print person.name ... Grandma L. 


For sampling, also use methods:


If you like this short tutorial, be sure to visit the official documentation - there are a lot of interesting things, including recipes with solutions to common problems and a set of plug-ins that extend the basic functionality.

Bonus


The author in his blog was asked about the speed of ORM, to which he replied:

It is a quicker way to find out how to use it.

On my computer, peewee walked around Django and SQLAlchemy on most tasks, and showed comparable results in iterations and sample instances.


After that, he published the results of a benchmark on a githaba. The usual models and related via ForeignKey in various scenarios were tested. Very curious .

Who cares, the source:


A good alternative to alchemy, what do you think?

Source: https://habr.com/ru/post/207110/


All Articles