wagtail-longclaw/docs/walkthrough/products.rst

145 wiersze
5.3 KiB
ReStructuredText

.. _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 <http://docs.wagtail.io/en/v1.9/topics/pages.html>`_
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-block:: 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 <http://docs.wagtail.io/en/v1.9/topics/writing_templates.html>`_.
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 <https://github.com/JamesRamm/longclaw_demo>`_.
Adding Products to the Basket
-----------------------------
Longclaw offers a helpful template tag to create an ``Add To Basket`` button for your products.
In your template, load the longclawbasket tags::
.. code-block:: django
{% load longclawbasket_tags %}
You can now use the tag to render a button for each product variant:
.. code-block:: django
{% add_to_basket_btn variant.id btn_text="Add To Basket" btn_class="btn btn-default" %}
If you wish to create a button manually, you can handle the click event by making an AJAX call to the longclaw API.
Situations where you would prefer this over the tempaltetag might be to support non-button elements, such as
dropdown buttons, or for React-based frontends.
Here is an example with a single button whose 'variant id' will change depending on the selection in a dropdown box.
We can acheive the drop down like this:
.. code-block:: django
<dl>
<dt>Format</dt>
<dd>
<div class="col-md-6">
<select id="variant-select">
{% for variant in page.variants.all %}
<option value="{{variant.id}}">{{variant.music_format}}</option>
{% endfor %}
</select>
</div>
</dd>
</dl>
Add a button:
.. code-block:: django
<button id="add-button">Add To Basket</button>
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 <basket>` allows all such interactions and all front end design decisions such as these are left up to the developer.
It is worthwhile looking at the longclaw demo source code to see how e.g. a basket & item count in the page header is implemented.