Coverage for /home/chris/workspace/django-shop/shop/models/productmodel: 97.62%

# Coverage for /home/chris/workspace/django-shop/shop/models/productmodel : 97.62%

## 40 statements 39 run 1 missing 0 excluded 0 partial

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | # -*- coding: utf-8 -*- from django.core.urlresolvers import reverse from django.db import models from polymorphic.manager import PolymorphicManager from polymorphic.polymorphic_model import PolymorphicModel from shop.util.fields import CurrencyField from django.db.models import Count from django.utils.translation import ugettext_lazy as _ class ProductStatisticsManager(PolymorphicManager): """ A Manager for all the non-object manipulation needs, mostly statistics and other "data-mining" toys. """ def top_selling_products(self, quantity): """ This method "mines" the previously passed orders, and gets a list of products (of a size equal to the quantity parameter), ordered by how many times they have been purchased. """ # Importing here is fugly, but it saves us from circular imports... from shop.models.ordermodel import OrderItem # Get an aggregate of product references and their respective counts top_products_data = OrderItem.objects.values( 'product_reference').annotate( product_count=Count('product_reference') ).order_by('product_count' )[:quantity] # The top_products_data result should be in the form: # [{'product_reference': '<product_id>', 'product_count': <count>}, ...] top_products_list = [] # The actual list of products for values in top_products_data: prod = Product.objects.get(pk=values.get('product_reference')) # We could eventually return the count easily here, if needed. top_products_list.append(prod) return top_products_list class ProductManager(PolymorphicManager): """ A more classic manager for Product filtering and manipulation. """ def active(self): return self.filter(active=True) class Product(PolymorphicModel): """ A basic product for the shop Most of the already existing fields here should be generic enough to reside on the "base model" and not on an added property """ name = models.CharField(max_length=255, verbose_name=_('Name')) slug = models.SlugField(verbose_name=_('Slug')) active = models.BooleanField(default=False, verbose_name=_('Active')) date_added = models.DateTimeField(auto_now_add=True, verbose_name=_('Date added')) last_modified = models.DateTimeField(auto_now=True, verbose_name=_('Last modified')) unit_price = CurrencyField(verbose_name=_('Unit price')) # Managers objects = ProductManager() statistics = ProductStatisticsManager() class Meta(object): app_label = 'shop' verbose_name = _('Product') verbose_name_plural = _('Products') def __unicode__(self): return self.name def get_absolute_url(self): return reverse('product_detail', args=[self.slug]) def get_price(self): """ Return the price for this item (provided for extensibility) """ return self.unit_price def get_name(self): """ Return the name of this Product (provided for extensibility) """ return self.name