QuerySet
- class sheraf.queryset.QuerySet(iterable=None, model_class=None, predicate=None, primary_key=None, **kwargs)[source]
Bases:
object
A
QuerySet
is a collection containingModel
instances. Like in a regularset
, objects are unique, but the main difference is thatQuerySet
keeps the insertion order.- Parameters:
iterable (Iterable) – A collection of models. If iterable is None, then model must be set.
model_class – A model class to iterate over. If model is None, then iterable must be set. If both are set, model_class is ignored.
predicate (Predicate) – a callable takes an instance as parameter and return a Boolean (if True, the instance will be returned in the iteration). If None, everything is returned.
kwargs – A dictionnary containing the values expected from the model parameters. If kwargs is {“foo”: “bar”} then the queryset will only contains models which attribute foo is “bar”.
For the following examples, let us work with a simple Cowboy model. For the sake of simplicity we use a
IntOrderedNamedAttributesModel
so the first instance created will have id 0, the second will have id 1 and so on…>>> class Cowboy(sheraf.IntOrderedNamedAttributesModel): ... table = "queryset_people" ... name = sheraf.SimpleAttribute() ... age = sheraf.SimpleAttribute() ... >>> with sheraf.connection(commit=True): ... peter = Cowboy.create(name="Peter", age=30) ... steven = Cowboy.create(name="Steven", age=30) ... george = Cowboy.create(name="George Abitbol", age=50)
QuerySet
are mostly created by doing requests on a Model withall()
,filter()
ororder()
, but can also be initialized with custom data.>>> with sheraf.connection(): ... a = Cowboy.all() # returns a QuerySet with all Cowboy ... b = QuerySet([peter, steven, george]) # This is an equivalent custom QuerySet ... assert list(a) == list(b)
QuerySet
behave like iterators, and can only be consumed once.>>> with sheraf.connection(): ... everybody = Cowboy.all() ... assert [peter, steven, george] == list(everybody) ... assert [] == everybody
Note
QuerySet
can be compared against anything iterable, but the comparison will consume theQuerySet
.QuerySet
keeps the order of insertion.>>> assert QuerySet([peter, steven]) != QuerySet([steven, peter])
QuerySet
supports slicing. Slices returns anotherQuerySet
.>>> with sheraf.connection(): ... assert peter == Cowboy.all()[0] ... assert QuerySet([peter, steven]) == Cowboy.all()[0:2] ... assert QuerySet([peter, steven, george]) == Cowboy.all()[0:]
- copy()[source]
Copies the
QuerySet
without consuming it.>>> with sheraf.connection(): ... peter = Cowboy.create(name="Peter") ... steven = Cowboy.create(name="Steven") ... george = Cowboy.create(name="George") ... qall = Cowboy.all() ... qcopy = qall.copy() ... ... assert [peter, steven, george] == qall ... # now qall is consumed ... ... assert [peter, steven, george] == qcopy ... # now qcopy is consumed
- delete()[source]
Delete the objects contained in the queryset.
Avoids problems when itering on deleted objects.
- filter(predicate=None, **kwargs)[source]
Refine a copy of the current
QuerySet
with further tests.- Parameters:
predicate (callable object) – filter instance by returning a truthy value. If None everything is selected.
kwargs (A dictionary which keys must be valid attributes of the model iterated.) – A dictionnary containing the values expected from the model parameters. If
kwargs
is{"foo": "bar"}
then the queryset will only contains models which attributefoo
is"bar"
.
- Returns:
A copy of the current
QuerySet
refined with further tests.- Return type:
It is possible to chain
filter()
calls:>>> with sheraf.connection(): ... assert Cowboy.filter(name="George Abitbol", age=50) == \ ... Cowboy.filter(name="George Abitbol").filter(age=50) ... >>> with sheraf.connection(): ... assert Cowboy.filter(lambda person: "Abitbol" in person.name, age=50) == \ ... Cowboy.filter(lambda person: "Abitbol" in person.name).filter(age=50)
An attribute cannot be filtered twice:
>>> with sheraf.connection(): ... Cowboy.filter(age=30).filter(age=40) Traceback (most recent call last): ... sheraf.exceptions.InvalidFilterException: Some filter parameters appeared twice
Note
Filtering on indexed attributes is more performant than filtering on non-indexed attributes. See
index()
.
- get()[source]
If the
QuerySet
contains one, and only one item, this method returns the item. If theQuerySet
contains several objects, it raises aQuerySetUnpackException
. If theQuerySet
is empty, it raises aEmptyQuerySetUnpackException
.>>> with sheraf.connection(): ... peter = Cowboy.create(name="Peter") ... steven = Cowboy.create(name="Steven") ... assert peter == Cowboy.filter(name="Peter").get() ... Cowboy.all().get() Traceback (most recent call last): ... sheraf.exceptions.TooManyValuesSetUnpackException: Trying to unpack a QuerySet with multiple elements <QuerySet model=Cowboy> >>> with sheraf.connection(): ... Cowboy.filter(age=30).get() Traceback (most recent call last): ... sheraf.exceptions.EmptyQuerySetUnpackException: Trying to unpack an empty QuerySet >>> with sheraf.connection(): ... Cowboy.filter(name="Unknown cowboy").get() Traceback (most recent call last): ... sheraf.exceptions.EmptyQuerySetUnpackException: Trying to unpack an empty QuerySet
- order(*args, **kwargs)[source]
Copies the current
QuerySet
and adds more order to it.- Parameters:
args (
sheraf.ASC
orsheraf.DESC
) – There can be only one positionnal argument. Choose to iterate over ids in an ascending or a descending way.kwargs (A dictionary which keys must be valid attributes of the model iterated, and the values must be
sheraf.ASC
orsheraf.DESC
) – Further parameters will set an order on the matching model attributes.
- Returns:
A copy of the current
QuerySet
with refined order.- Return type:
The default order is the ascending model ids.
>>> with sheraf.connection(commit=True): ... peter = Cowboy.create(name="Peter", age=35) ... steven = Cowboy.create(name="Steven", age=35) ... george = Cowboy.create(name="George", age=50) ... >>> with sheraf.connection(): ... assert [peter, steven, george] == Cowboy.all() ... assert [peter, steven, george] == Cowboy.all().order(sheraf.ASC) ... assert [george, steven, peter] == Cowboy.all().order(sheraf.DESC) ... ... assert [george, peter, steven] == Cowboy.all().order(name=sheraf.ASC) ... assert [steven, peter, george] == Cowboy.all().order(name=sheraf.DESC)
Several order parameters can be passed, either as arguments of the function, or by calling
order()
calls.>>> with sheraf.connection(): ... assert [george, peter, steven] == Cowboy.all().order(age=sheraf.DESC, name=sheraf.ASC)
- search(**kwargs)[source]
Refine a copy of the current
QuerySet
with further tests.This method is very similar to
filter()
except the values it takes are transformed with the same way values are transformed at indexation. TODO: pas très clairFor instance, if an attribute indexes its values with a lowercase search_func, the
search()
attributes will go through the same search_func. Hence it allows to pass uppercase filter values, whilefilter()
does not allow this.>>> class MyCustomModel(sheraf.Model): ... table = "my_custom_model" ... my_attribute = sheraf.SimpleAttribute().index( ... index_keys_func=lambda string: {string.lower()} ... ) ... >>> with sheraf.connection(commit=True): ... m = MyCustomModel.create(my_attribute="FOO") ... >>> with sheraf.connection(): ... assert [m] == MyCustomModel.search(my_attribute="foo") ... assert [m] == MyCustomModel.filter(my_attribute="foo") ... ... assert [m] == MyCustomModel.search(my_attribute="FOO") ... assert [] == MyCustomModel.filter(my_attribute="FOO")