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

  from django.db import models
  
  
- class ProductManager(models.Manager):
+ class ProductQuerySet(models.query.QuerySet):
  
      def base_queryset(self):
          """
-         Return ``QuerySet`` with related content pre-loaded.
+         Applies select_related and prefetch_related for commonly related
+         models to save on queries
          """
-         return self.get_query_set().select_related('product_class')\
+         return self.select_related('product_class')\
              .prefetch_related('variants',
                                'product_options',
                                'product_class__options',
                                'stockrecords',
                                'images',
-                               ).all()
+                               )
+ 
+     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_query_set(self):
+     def get_queryset(self):
-         return super(BrowsableProductManager, self).get_query_set().filter(
+         return super(BrowsableProductManager, self).get_queryset().browsable()
-             parent=None)
  
Allow chaining of Product's custom querysets
## Code Before:
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)

## Instruction:
Allow chaining of Product's custom querysets
## Code After:
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()
