from django.db import models


class ProductManager(models.Manager):

    def base_queryset(self):
        """
        Return ``QuerySet`` with related content pre-loaded.
        """
        return self.get_query_set().select_related('product_class')\
            .prefetch_related('variants',
                              'product_options',
                              'product_class__options',
                              'stockrecords',
                              'images',
                              ).all()


class BrowsableProductManager(ProductManager):
    """
    Excludes non-canonical products
    """

    def get_query_set(self):
        return super(BrowsableProductManager, self).get_query_set().filter(
            parent=None)

from django.db import models


class ProductQuerySet(models.query.QuerySet):

    def base_queryset(self):
        """
        Applies select_related and prefetch_related for commonly related
        models to save on queries
        """
        return self.select_related('product_class')\
            .prefetch_related('variants',
                              'product_options',
                              'product_class__options',
                              'stockrecords',
                              'images',
                              )

    def browsable(self):
        """
        Excludes non-canonical products.
        """
        return self.filter(parent=None)


class ProductManager(models.Manager):
    """
    Uses ProductQuerySet and proxies its methods to allow chaining

    Once Django 1.7 lands, this class can probably be removed:
    https://docs.djangoproject.com/en/dev/releases/1.7/#calling-custom-queryset-methods-from-the-manager  #n oqa
    """

    def get_queryset(self):
        return ProductQuerySet(self.model, using=self._db)

    def browsable(self):
        return self.get_queryset().browsable()

    def base_queryset(self):
        return self.get_queryset().base_queryset()


class BrowsableProductManager(ProductManager):
    """
    Excludes non-canonical products

    Could be deprecated after Oscar 0.7 is released
    """

    def get_queryset(self):
        return super(BrowsableProductManager, self).get_queryset().browsable()

Allow chaining of Product's custom querysets
Allow chaining of Product's custom querysets

This aligns the implementation of Oscar specific QuerySet Methods with
the implementation in current django core[1].
While this is not DRY, it does deliver on chainability and can be seen
as preparation to take advantage of the improvements coming to this part
of django in 1.7 [2]

The original motivation for this was that using a custom QuerySet while
trying not to copy code from oscar felt too hard.

[1] https://github.com/django/django/blob/1.6.2/django/db/models/manager.py#L123
[2] https://docs.djangoproject.com/en/dev/releases/1.7/#calling-custom-queryset-methods-from-the-manager

Fixes #1278.

Deprecation comments added by @maikhoepfel
