Memory DB is a Django like database manager using in-memory objects.
Unlike Django QuerySet, current version don't return new QuerySets when filtering on them.
initial = Model.objects.all()
filtered_1 = initial.filter(...)
filtered_2 = initial.filter(...) # don't do thatOtherwise filtered_1 will also be filtered.
from memory_db import MemoryManager, MemoryMeta, MemoryModel
class PersonManager(MemoryManager):
def get_all(self):
with open('persons.yml', mode='r', encoding='utf8') as stream:
content = yaml.safe_load(stream)
return [
self.model.from_db(row)
for row in content:
]
class Person(MemoryModel):
objects = PersonManager()
class Meta(MemoryMeta):
fields = [
models.CharField(name='first_name', max_length=30),
models.CharField(name='last_name', max_length=30),
]The list of data fields is define in the field list of the Meta.
Almoste all django differences could be considered as new features.
As you could see in above example, contrary to Django, the fields are directly populated in the fields of the Meta class of the model.
This might be an evolution to the future
In memory_db project the manager take the role of the database, by returning the data in the get_all method.
ForeignKey, ManyToManyField and OneToOneField fields management is not implemented (yet).
You may use MemoryRelatedManager:
class Topping(MemoryModel):
# ...
pass
class PizzaManager(MemoryManager):
def get_all(self) -> Iterable['Pizza']:
"""Create test models with relation."""
margarita = Pizza()
margarita.toppings.add(Topping(), Topping())
return [margarita]
class Pizza(MemoryModel):
objects = PizzaManager()
toppings: 'MemoryRelatedManager[Topping]'
def __init__(self):
"""Init the MemoryRelatedManager."""
super().__init__()
self.toppings = MemoryRelatedManager(Topping)Note: all related elements are not store in the related MemoryModel manager.
You may want to check your data integrity according to you model. However data checks are not automatically added for each model managers.
You can create a check by calling the check_data of the MemoryModel.
Example:
from django.core.checks.messages import CheckMessage
from django.core import checks
from memory_db import MemoryManager, MemoryModel
class PersonManager(MemoryManager):
def get_all(self):
pass
def check_data(self):
errors: List[CheckMessage]
with open('persons.yml', mode='r', encoding='utf8') as stream:
content = yaml.safe_load(stream)
for row in content:
errors += self.model.check_data(row)
return error
class Person(MemoryModel):
objects = PersonManager()
@checks.register
def check_persons()
return Person.objects.check_data()filter(**kwargs)
Filter the current queryset by only keeping the objects that match the given lookup parameters.
The lookup parameters (**kwargs) should be in the format described in Field lookups below.
exclude(**kwargs)
Filter the current queryset by removing the objects that match the given lookup parameters.
The lookup parameters (**kwargs) should be in the format described in Field lookups below.
This example excludes all entries whose pub_date is later than 2005-1-3 AND whose headline is “Hello”:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')This example excludes all entries whose pub_date is later than 2005-1-3 OR whose headline is “Hello”:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')Not implemented yet
order_by(*fields)
By default, results returned by a QuerySet depends on the get_all result of your MemoryManager. You can override this by using the order_by method.
reverse()
Work as Django QuerySet reverse
Not implemented yet
values(*fields)
Work as Django QuerySet values
>>> Blog.objects.values('id', 'name')
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>Keyword arguments and non-positional arguments aren't implemented yet.
values_list(*fields, flat=False)
Work as Django QuerySet values_list
>>> Entry.objects.values_list('id', 'headline')
<QuerySet [(1, 'First entry'), ...]>
>>> Entry.objects.values_list('id').order_by('id')
<QuerySet[(1,), (2,), (3,), ...]>
>>> Entry.objects.values_list('id', flat=True).order_by('id')
<QuerySet [1, 2, 3, ...]>Keyword argument named: bool is not implemented yet
Not implemented yet
all()
Reset the iterator to the initial state
Disclamer: this method different from the Django all method
Not implemented yet
get(**kwargs)
Returns the object matching the given lookup parameters, which should be in the format described in Field lookups. You should use lookups that are guaranteed unique, such as the primary key or fields in a unique constraint. For example:
Entry.objects.get(id=1)
Entry.objects.get(blog=blog, entry_number=1)Work as Django QuerySet get
count()
Work as Django QuerySet count
# Returns the total number of entries in the database.
Entry.objects.count()
# Returns the number of entries whose headline contains 'Lennon'
Entry.objects.filter(headline__contains='Lennon').count()iterator()
Evaluates the QuerySet (by performing the query) and returns an iterator, as Django QuerySet iterator() does.
Not implemented yet
first()
Work as Django QuerySet first()
Article.objects.order_by('title', 'pub_date').first()last()
Works like first(), but returns the last object in the queryset.
exists()
Works as Django QuerySet exists()
Field lookups are how you specify the meat of an SQL WHERE clause. They’re specified as keyword arguments to the QuerySet methods filter(), exclude() and get().
For an introduction, see models and database queries documentation.
Built-in lookups are listed below :
Exact match. Use : operator.eq
Examples:
Entry.objects.get(id__exact=14)
Entry.objects.get(id__exact=None)Case-insensitive exact match. Use : icast_op(operator.eq)
Example:
Blog.objects.get(name__iexact='beatles blog')
Blog.objects.get(name__iexact=None)Case-sensitive containment test. Use : operator.contains
Example:
Entry.objects.get(headline__contains='Lennon')Case-insensitive containment test. Use : icast_op(operator.contains)
Example:
Entry.objects.get(headline__icontains='Lennon')In a given iterable; often a list, tuple, or queryset. It’s not a common use case, but strings (being iterables) are accepted.
Use : operator.contains
Examples:
Entry.objects.filter(id__in=[1, 3, 4])
Entry.objects.filter(headline__in='abc')Greater than. Use : operator.gt
Example:
Entry.objects.filter(id__gt=4)Less than or equal to. Use : operator.le
Less than. Use : operator.lt
Greater than or equal to. Use : operator.ge
Case-sensitive starts-with. Use : str.startswith
Example:
Entry.objects.filter(headline__startswith='Lennon')Use : icast_op(str.startswith)
Example:
Entry.objects.filter(headline__istartswith='Lennon')Use : str.endswith
Example:
Entry.objects.filter(headline__endswith='Lennon')Use : icast_op(str.endswith)
Example:
Entry.objects.filter(headline__iendswith='Lennon')Takes either True or False, which check if the value is None or is not None, respectively.
Example:
Entry.objects.filter(pub_date__isnull=True)Not implemented yet