I have a project based on django-oscar
(and django-cms
), which runs on multiple domains with different SITE_ID
s using the django.contrib.sites
module. The project is already productive and i can't change the category slugs anymore - Also switching the entire code to Nested Set Trees or Adjacent Trees is something i wish to avoid - for your better understanding: The initial requirements did not want a different category sorting for each domain, so i just used Oscars default category implementation.
But since Oscars category model/manager is based on django-treebeard
s materialized path tree implementation, i have to consider a few differences to the usual Django-way of changing the default ordering.
Given these two extra fields in the model (which inherits from django-oscar
s AbstractCategory)
class Category(AbstractCategory):
# ...
order_site_1 = models.IntegerField(
null=False,
default=0
)
order_site_2 = models.IntegerField(
null=False,
default=0
)
I can't simply add the ordering to the meta class like:
class Category(AbstractCategory):
class Meta:
ordering = ['depth', '-order_site_{}'.format(Site.objects.get_current().id), 'name']
First, it will ignore this directive since treebeard
s MP_NodeManager.get_queryset()
does not respect custom sorting - for the MP_Tree logic it has to rely on a sorting generated at insertion time (which is stored in path
), so this approach would defy the purpose of MP_Tree itself.
I also had a look at node_order_by
- but as stated in the docs:
Incorrect ordering of nodes when
node_order_by
is enabled. Ordering is enforced on node insertion, so if an attribute innode_order_by
is modified after the node is inserted, the tree ordering will be inconsistent.
But again on multiple domains with different category ordering this is of no use. The only way left which i can think of is to override the MP_NodeManager
class:
class CustomOrderQuerySet(MP_NodeManager):
def get_queryset(self):
sort_key = '-order_site_{}'.format(Site.objects.get_current().id)
return MP_NodeQuerySet(self.model).order_by('depth', sort_key, 'name')
But this approach is clearly wrong, because MP_Tree relies on path
sorting to generate a proper Tree - what i thought about is iterating over all entries, compare the path
, ignore the last part and sort according to order_site_{id}
and re-convert it to a QuerySet
.
I am not even sure if that is possible, and i want to avoid to go there, so my question is: Is there a way to reflect this logic within a chain of ORM statements, so that i can continue using a native QuerySet
?