I want in my homepage to show the furnitures items in a following way:

Newly Arrived Furnitures(upto 10)

Featured Furnitures

Free shipping Furnitures (upto 10)

For this I tried to go with the principle of Fat Models, Thin View. Here is my code

class FurnitureQuerySet(models.QuerySet):
    def active(self):
        return self.filter(is_active=True)

    def featured(self):
        return self.active().filter(is_featured=True)

    def new_arrival(self, max_furnitures):
        return self.active().order_by('-id')[:max_furnitures]

    def free_shipping(self, max_furnitures):
        return self.active().filter(is_free_shipping=True)[:max_furnitures]

class FurnitureManager(models.Manager):
    def get_queryset(self):
        return FurnitureQuerySet(self.model, using=self._db)

    def all(self):
        return self.get_queryset().active()

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

    def new_arrival(self, max_furnitures):
        return self.get_queryset().new_arrival(max_furnitures)

    def free_shipping(self, max_furnitures):
        return self.get_queryset().free_shipping(max_furnitures)

    def get_by_id(self, slug):
        qs = self.get_queryset().filter(slug=slug)
        if qs.count() == 1:
            return qs.first()
        return None

class Furniture(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)
    manufacturer = models.ForeignKey(Manufacturer, blank=True, null=True)
    slug = models.SlugField(max_length=200, unique=True)
    is_active = models.BooleanField(
    default=True, help_text='Furniture is available for listing and sale')
    is_featured = models.BooleanField(
        default=False, help_text='Promote this furniture on main pages')
    is_free_shipping = models.BooleanField(
        default=False, help_text='No shipping charges')
    timestamp       = models.DateTimeField(auto_now_add=True)
    objects         = FurnitureManager()

def home(request):
    categories = Category.objects.root_nodes()
    furnitures = Furniture.objects.new_arrival(10)
    featured_furnitures = Furniture.objects.featured()
    shipping_free_furnitures = Furniture.objects.free_shipping(10)
    context = {
        'categories': categories,
        'furnitures': furnitures,
        'featured': featured_furnitures,
        'shipping_free': shipping_free_furnitures,
    return render(request, 'home.html', context)

The template will be:

<h1>Newly Arrival</h1>
{% for new_furniture in furnitures %}
  {{ new_furniture.name }}
{% endfor %}

{% for featured_furniture in featured %}
  {{ featured_furniture.name }}
{% endfor %}

Do take care to run flake8 over the source, and follow its advice.

Array slicing [:max_furnitures] is idiomatic and nice. But if you have a thousand or a million items, you will prefer to use SQL limit, so you don't retrieve a ton of items from the DB only to discard them. You will get a different execution plan from the backend DB if you expose limit 10 to its query optimizer.

I see four different max_furnitures parameters. Now maybe this is perfectly nice and we prefer to leave it as is. But also consider introducing it as an attribute used by constructor.

Looks good.

Ship it.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.