.. _tutorial_products: Managing the Catalogue ====================== Creating the Product Index -------------------------- Wagtails' ``Page`` models are organized in a tree structure. All our ``Product`` pages will therefore need a parent. This is provided by the ``ProductIndex`` model. .. note:: Read more about Wagtail pages in the `Wagtail docs `_ To add a product index page: - Navigate to the admin and log in - Select the homepage from the explorer menu - Select ``add child page`` - Select ``Product index`` and enter the title (e.g. `Products`) .. figure:: ../_static/images/product_index.png 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``. The ``Product`` model is fairly minimal. It has: - A title - A description - One or more ``ProductVariant``s - Optionally some images and tags .. figure:: ../_static/images/product.png Customising Variants -------------------- The ``ProductVariant`` model is where we can customise the attributes of our model. Running ``longclaw start`` provided a ``products`` with a minimal implementation of a custom ``ProductVariant`` model. We can further customise this now by opening ``my_shop/products/models.py`` in a text editor. ``ProductVariant`` inherits from ``ProductVariantBase`` which provides the ``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. As we are creating a music shop, we are going to add a ``music_format`` field to the model. We will also remove the ``description`` field as we dont have any real need for it at the moment: .. code:: python class ProductVariant(ProductVariantBase): _MUSIC_FORMAT_CHOICES = ( (1, 'CD'), (2, 'Vinyl'), ) music_format = models.IntegerField(max_length=3, choices=_MUSIC_FORMAT_CHOICES) After making and running migrations, we can now select the format for each variant: .. figure:: ../_static/images/product_variant.png The actual model used for the product variant can be changed by changing the ``PRODUCT_VARIANT_MODEL`` setting in your ``settings.py`` Creating the Front End ======================= Since ``ProductIndex`` and ``Product`` are Wagtail pages, we write templates for them just like any other page. The Wagtail documentation already comprehensively covers `writing templates `_. Our template project already has some basic templates for ``ProductIndex`` and ``Product``: - ``my_shop/my_shop/templates/longclawproducts/product_index.html`` - ``my_shop/my_shop/templates/longclawproducts/product.html`` They contain just enough information to demonstrate how to traverse the products and their fields. For a more complete template, take a look at the `demo project `_. Adding Products to the Basket ----------------------------- An important detail of the product template is providing the ability to add or remove a product to the basket. This is done by making AJAX calls to the longclaw API. In the product template, we would like to provide a means to select a variant and add it to the basket. For t-shirts, our variants are going to represent different sizes, so we would like a single ``Add`` button and a drop down of sizes. We can acheive the drop down like this: .. code-block:: django
Format
Add a button: .. code-block:: django We can then write a jquery function to handle the click event: .. code-block:: javascript $('#add-button').click(function () { // Selected variant var variant_id = $('#variant-select option:selected').val(); // Add to the basket $.post("api/add_to_basket/", { variant_id: variant_id }); }); This is a basic example of integrating with the basket. You will likely need to incorporate more complex designs such as displaying a count of items in the basket, allowing the user to increase/decrease quantity and so on. The :ref:`basket API ` allows all such interactions and all front end design decisions such as these are left up to the developer