work on QCombine, add QCombined

This commit is contained in:
bkfox 2016-06-20 19:23:42 +02:00
parent bc87e635c2
commit ceecbcfa54
4 changed files with 88 additions and 27 deletions

View File

@ -13,6 +13,7 @@ class QCombine:
- when working on fields, we assume that they exists on all of them;
- for efficiency, there is no possibility to change order per field;
to do so, do it directly on the querysets
- we dont clone the combinator in order to avoid overhead
"""
order_fields = None
lists = None
@ -21,20 +22,39 @@ class QCombine:
"""
lists: list of querysets that are used to initialize the stuff.
"""
self.lists = lists or []
self.lists = list(lists) or []
def map(self, qs_func, non_qs = None):
"""
Map results of qs_func for QuerySet instance and of non_qs for
the others (if given), because QuerySet always clones itself.
"""
for i, qs in self.lists:
if issubclass(type(qs, QuerySet):
self.lists[i] = func(qs)
elif non_qs:
self.lists[i] = non_qs(qs)
def all(self):
self.map(lambda qs: qs.all())
def filter(self, **kwargs):
for qs in self.lists:
if issubclass(type(qs), QuerySet):
qs.filter(**kwargs)
self.map(lambda qs: qs.filter(**kwargs))
return self
def exclude(self, **kwargs):
for qs in self.lists:
if issubclass(type(qs), QuerySet):
qs.exclude(**kwargs)
self.map(lambda qs: qs.exclude(**kwargs))
return self
def distinct(self, **kwargs):
self.map(qs.distinct())
return self
def get(self, **kwargs):
self.filter(**kwargs)
it = iter(self)
return next(it)
def order_by(self, *fields, reverse = False):
"""
Order using these fields. For compatibility, if there is
@ -49,28 +69,72 @@ class QCombine:
self.order_reverse = reverse
self.order_fields = fields
for qs in self.lists:
if issubclass(type(qs), QuerySet):
qs.order_by(*fields)
else:
qs.sort(key = operator.attrgetter(fields),
reverse = reverse)
self.map(
lambda qs: qs.order_by(*fields),
lambda qs: sorted(
qs,
qs.sort(
key = operator.attrgetter(fields),
reverse = reverse
)
)
)
return self
def clone(self):
"""
Make a clone of the class. Not that lists are copied, non-deeply
"""
return QCombine(*[
qs.all() if issubclass(type(qs), QuerySet) else qs.copy()
for qs in self.lists
])
def __len__(self):
return sum([len(qs) for qs in self.lists])
def __iter__(self):
if self.order_fields:
if not self.order_fields:
return itertools.chain(self.lists)
# FIXME: need it lazy?
return heapq.merge(
*self.lists,
key = operator.attrgetter(*self.order_fields),
reverse = self.order_reverse
)
return itertools.chain(self.lists)
def __getitem__(self, k):
if type(k) == slice:
return list(itertools.islice(iter(self), k.start, k.stop, k.step))
return list(itertools.islice(iter(self), k))
it = itertools.islice(iter(self), k.start, k.stop, k.step)
else:
it = itertools.islice(iter(self), k)
return list(it)
class QCombined:
"""
This class is used to register a route for multiple models to a website.
A QCombine is created with qs for all given models when objects
property is retrieved.
Note: there no other use-case.
"""
def __init__(*models):
self.models = models
self._meta = self.Meta()
class Meta:
verbose_name = _('publication')
verbose_name_plural = _('publications')
@property
def objects(self):
"""
The QCombine that is returned actually holds the models' managers,
in order to simulate the same behaviour than a regular model.
"""
qs = QCombine([model.objects for model in self.models])
return qs

View File

@ -5,7 +5,6 @@ from django.contrib.contenttypes.models import ContentType
from django.utils import timezone
from django.utils.translation import ugettext as _, ugettext_lazy
class Route:
"""
Base class for routing. Given a model, we generate url specific for each

View File

@ -146,7 +146,6 @@ class PostListView(BaseView, ListView):
return super().dispatch(request, *args, **kwargs)
def get_queryset(self):
print('get_query_set')
if self.route:
qs = self.route.get_queryset(self.model, self.request,
**self.kwargs)
@ -193,7 +192,6 @@ class PostListView(BaseView, ListView):
self.model, self.request, **self.kwargs
)
print([post.title for post in context.get('object_list')])
context['list'] = self.list
return context

View File

@ -9,7 +9,6 @@
- programs:
- schedule:
- (old) schedule.to_string unused? commented
- check one week on two
- write more tests
- sounds:
- inline admin
@ -25,9 +24,10 @@
- cms.views
- cms.parts
- cms.script
- cms.qcombine
- routes
- customized header depending on the list (e.g. thread -> link to thread parent)
- different models combinaison
- integrate QCombine
- admin cms
- content management -> do we use a markup language?
- sections: