Adding Products
Topics covered:
- Creating the
ProductIndex
andProductVariant
model - Customising the models
- Adding products via the admin
Initial Models
Longclaw makes as few assumptions as possible when it comes to modelling your products, since the requirements of different shops can be wide and varied.
You must create a ProductVariant
model (it can be called anything) and implement
a small number of fields Longclaw expects.
The easiest way to do this is by inheriting from longclaw.products.ProductVariantBase
.
Head over to catalog/models.py
. You will see that longclaw created the following basic models for you:
ProductIndex
. This model is used for listings of products.Product
. This is the model of a single product type. In our bakery, we might have a 'Farmhouse Loaf' product.ProductVariant
. This model captures variations of a product. For example, we might offer our 'Farmhouse Loaf' using different flour types, different sizes, sliced or not sliced all for different prices. Note that it inherits fromProductVariantBase
. This is important since there are small number of fields (such as price) that other longclaw packages expect to be present in order to function correctly.
This is just one way of modelling yor catalogue but you are not bound to it.
ProductVariant
is the only model required by Longclaw and precisely what this represents is up to your (e.g. it could be the product itself, or, as the name suggests, a variant of a product). You could create multiple 'index' pages, perhaps representing different lines aswell as multiple 'product' type pages, or do away withProduct
completely.
Customising
The ProductVariantBase
model provides the base_price
, ref
and slug
fields.
The ref
field is intended to be used as a short description or sub-title to help distinguish a particular variant.
The slug
field is autogenerated from the ref
and the parent Product
title.
ProductVariant
,Product
andProductIndex
are all WagtailPage
s. If you are not familiar, it is important that you take a look at the Wagtail documentation before going further.
In our bakery, there are other product attributes we want to capture. We should add these to the ProductVariant
model. Lets just consider a couple of basic fields:
- Is it gluten free or not?
- Suitable for vegetarians?
Lets adjust the ProductVariant
model to reflect this:
class ProductVariant(ProductVariantBase):
gluten_free = models.BooleanField(default=False)
vegetarian = models.BooleanField(default=False)
Dynamic Pricing
The ProductVariant
model can be configured so that the price is dynamically calculated. This is great - we can selectively apply a discount to our variants (or do anything else for that matter)!
The ProductVariant
model provides a price
property which is used throughout longclaw. By default, it simply returns the base_price
attribute.
We can override it to hold our custom price calculation.
For our bakery, I've decided that I want to be able enable a variable discount whenever we like.
So lets add a couple more fields to our model to provide the discount information:
discount = models.BooleanField(default=False)
discount_percent = models.PositiveSmallIntegerField(
default=20,
validators=[
MaxValueValidator(75)
]
)
Since I don't want to make mistakes and start offering my bread for free, I have limited the maximum discount to 75%. Finally, lets override the price getter to apply the discount:
@ProductVariantBase.price.getter
def price(self):
if self.discount:
discount_price = self.base_price * Decimal((100 - self.discount_percent) / 100.0 )
return discount_price.quantize(Decimal('.01'), decimal.ROUND_HALF_UP)
return self.base_price
Now, create and run the migrations for our catalog
app:
python manage.py makemigrations catalog
python manage.py migrate
Further to the product models, the project template (created by longclaw start
) also provided a ProductImage
model. If you do not want an image(s) related to the Product
model, delete this model and remove the InlinePanel
line from the Product
class.
I leave it as an exercise to the reader to allow images at the ProductVariant
level.
Using the Admin
The models are ready - Lets open up the admin and start adding our products.
Run the server:
python manage.py runserver
And navigate to localhost:8000/admin. You will need to sign in with the super user you created at the start of the tutorial.
Under 'Pages', select the root page:
On the 'Root' screen select 'Add Child Page' at the top. Here I selected my 'Home' page, but if you are running a small shop, you may wish your home page to be your product listing, in which case you might select 'Product Index'.
We can now add Product
models as children of ProductIndex
. Only pages of type Product
can be created under ProductIndex
.
Adding a Product
Under the explorer homepage, we should now see our newly created ProductIndex
. We can select Add child page
to add our first
Product
.
Add a title, description then start adding variants.
You will see that in the product variants are the custom fields we added for
applying discounts.
If we navigate back to the product index page, we see the new product listed: