QuerySet¶
-
class
sheraf.queryset.QuerySet(iterable=None, model_class=None, predicate=None, **kwargs)¶ Bases:
objectA
QuerySetis a collection containingModelinstances. Like in a regularset, objects are unique, but the main difference is thatQuerySetkeeps 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
IntOrderedNamedAttributesModelso 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)
QuerySetare 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 set(a) == set(b)
QuerySetbehave like iterators, and can only be consumed once.>>> with sheraf.connection(): ... everybody = Cowboy.all() ... assert {peter, steven, george} == set(everybody) ... assert [] == everybody
Note
QuerySetcan be compared against anything iterable, but the comparison will consume theQuerySet.QuerySetkeeps the order of insertion.>>> assert QuerySet([peter, steven]) != QuerySet([steven, peter])
QuerySetsupports slicing. Slices returns anotherQuerySet.>>> with sheraf.connection(): ... assert QuerySet([peter]) == Cowboy.all()[0] ... assert QuerySet([george]) == Cowboy.all()[-1] ... assert QuerySet([peter, steven]) == Cowboy.all()[0:2] ... assert QuerySet([peter, steven, george]) == Cowboy.all()[0:]
QuerySetsupports bitwise operations and, or and xor. All those operations consume the internal iterator.>>> assert QuerySet([peter]) | QuerySet([steven]) == QuerySet([peter, steven]) >>> assert QuerySet([peter, steven]) & QuerySet([steven]) == QuerySet([steven]) >>> assert QuerySet([peter, steven]) ^ QuerySet([steven]) == QuerySet([peter])
-
copy()¶ Copies the
QuerySetwithout 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
-
count()¶ - Returns
The number of objects in the
QuerySet, but consumes it.
>>> with sheraf.connection(): ... assert Cowboy.create() ... qs = Cowboy.all() ... assert qs.count() == 1 ... assert qs.count() == 0
-
delete()¶ Delete the objects contained in the queryset.
Avoids problems when itering on deleted objects.
-
filter(predicate=None, **kwargs)¶ Refine a copy of the current
QuerySetwith 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
kwargsis{"foo": "bar"}then the queryset will only contains models which attributefoois"bar".
- Returns
A copy of the current
QuerySetrefined 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()¶ If the
QuerySetcontains one, and only one item, this method returns the item. If theQuerySetcontains several objects, it raises aQuerySetUnpackException. If theQuerySetis 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.QuerySetUnpackException: Trying to unpack more than 1 value from a QuerySet >>> 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)¶ Copies the current
QuerySetand adds more order to it.- Parameters
args (
sheraf.ASCorsheraf.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.ASCorsheraf.DESC) – Further parameters will set an order on the matching model attributes.
- Returns
A copy of the current
QuerySetwith refined order.- Return type
The default order is the ascending model ids.
>>> with sheraf.connection(commit=True): ... peter = Cowboy.create(name="Peter") ... steven = Cowboy.create(name="Steven") ... george = Cowboy.create(name="George") ... >>> 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.Warning
Arguments order is only kept since
Python 3.6, so using multiple order parameters will result on undefined order forPython 3.5-. If you are usingPython 3.5-and need severalQuerySetorders, prefer chaining order method calls.>>> with sheraf.connection(): # TODO: not skip ... assert [george, peter, steven] == Cowboy.all().order(age=sheraf.DESC) ... assert [george, steven, peter] == Cowboy.all().order(age=sheraf.DESC) \ ... .order(name=sheraf.ASC) >>> # Only since Python 3.6 ... with sheraf.connection(): ... assert [george, steven, peter] == Cowboy.all().order(age=sheraf.DESC, name=sheraf.ASC)
-
search(**kwargs)¶ Refine a copy of the current
QuerySetwith 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 transformation, the
search()attributes will go through the same transformation. Hence it allows to pass uppercase filter values, whilefilter()does not allow this.>>> class MyCustomModel(sheraf.IntAutoModel): ... my_attribute = sheraf.SimpleAttribute().index( ... values=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")