Skip to content
This repository has been archived by the owner on Jan 10, 2024. It is now read-only.

Commit

Permalink
First part of new docs
Browse files Browse the repository at this point in the history
  • Loading branch information
patrys committed Apr 24, 2013
1 parent abc2cbe commit 4fc3a87
Show file tree
Hide file tree
Showing 15 changed files with 326 additions and 422 deletions.
2 changes: 2 additions & 0 deletions doc/cart.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:mod:`satchless.cart` --- shopping carts
========================================
14 changes: 6 additions & 8 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys, os

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
Expand All @@ -38,16 +36,16 @@

# General information about the project.
project = u'satchless'
copyright = u'2010-2011, Mirumee Software'
copyright = u'2010-2013, Mirumee Software'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2011.09'
version = '1.0'
# The full version, including alpha/beta/rc tags.
release = '2011.09 (prerelease)'
release = '1.0a0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down Expand Up @@ -120,7 +118,7 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
#html_static_path = ['_static']

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
Expand Down Expand Up @@ -172,8 +170,8 @@
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'satchless.tex', u'satchless Documentation',
u'Mirumee Software', 'manual'),
('index', 'satchless.tex', u'satchless Documentation',
u'Mirumee Software', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
Expand Down
Binary file removed doc/img/pricing-handlers-chain.png
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed doc/img/satchless-checkout-architecture-v2.png
Binary file not shown.
227 changes: 9 additions & 218 deletions doc/index.rst
Original file line number Diff line number Diff line change
@@ -1,227 +1,18 @@
.. _index:

=======================
Satchless: less is mo'
=======================
======================

A shop for perfectionists with deadlines and coding standards.
A pythonic way to deal with lower levels of e-commerce.


Overview
========

Satchless is a high-level framework that provides building blocks for an online
store. In contrast to many other e-commerce solutions Satchless only delivers
the necessery bricks, not an out-of-the-box shop. By putting all the parts
together you can easily tailor the solution to meet your exact requirements
with no pain and no ugly workarounds.

It's based on `Django`_ web application framework and written in `Python`_
language. The aim of this project is to make each module independent and
extensible. Using Satchless you will be able to quickly build:

* An online shop with:
* shippable products
* downloadable products
* with both of them or any other product type you may imagine
* discounts, wishlists and other popular features
* custom checkout process
* A cart which can be easily integrateed with many popular payment gateways
* A catalog of products
* A catalog with wishlists

.. _`Django`: http://djangoproject.org/
.. _`Python`: http://python.org/

The project is hosted on `GitHub`_, and the source code is available, as well as
an extensive test suite and some example applications.

.. _`GitHub`: http://github.com/mirumee/satchless

**Warning:** Satchless will shortly enter the beta stage of development and
it's currently perfectly possible to build a shop on top of it. However, you
should be prepared for some—sometimes also backward-incompatible—changes to
the code.


Main concepts
=============

Satchless is not a turn-key solution for online shops and is not meant to be
one. It should be considered to be a set of advanced, loosely coupled bricks
which can be turned into a working shop by a *programmer*.


The App
-------

The main idea behind the *Apps* is to provide an easy and flexible way of
extending Satchless. In short an *App* is a group of views sharing the same
logical and functional domain. The views are provided as methods of the *App*
object. You can treat the *App* itself as the context in which all of its views
execute. It means that apart from keeping the views logic, *App* is also
encapsulating the configuration (like model classes used by views, forms or
handlers).

Summarizing:

* *App* is a group of views sharing same logical and functional domain
* *App* is a context of view execution
* *App* encapsulates the configuration ie. model classes used by views,
forms, handlers etc.
* In particular to the above *App* takes care of the URLs and the their
namespace
* *Apps* can be aware of other apps and use them instead of duplicating all
the configuration (ie. an Order app uses the Cart app that in turn uses
the Product app)

Satchless comes with a number of most important *Apps*. You can use them
out-of-the-box and/or easily extend or customise their behavior according to
your requirements:

* **Product app**
:ref:`Details` |
:ref:`Customisation example`
* **Category app**
:ref:`Details` |
:ref:`Customisation example`
* **Cart app**
:ref:`Details` |
:ref:`Customisation example`
* **Order app**
:ref:`Details` |
:ref:`Customisation example`
* **Checkout app** (abstract)
:ref:`Details` |
:ref:`Customisation example`


Deferred keys
-------------

Unfortunately, Django does not provide a pluggable way to say “here we want to
refer to an external model, unfortunately we don't know *which model* yet”.

There are possible workarounds like declaring a foreign key using the
`"module.Model"` syntax but we want Satchless to be a library. Thus we will
never tell you that you absolutely have to call your product model “Eels” and
keep it in a module named “hovercraft” lest everything falls apart.

Our solution is to introduce a pseudo-field type named `DeferredField`. It comes
in various flavors like `DeferredForeignKey` and `DeferredManyToManyField` and
provides an insertion point for a future relation. The relation itself can be
created by calling `satchless.utils.models.construct()`:

.. code-block:: python
from django.db import models
from satchless.utils.models import construct, DeferredForeignKey
class AbstractTag(models.Model):
parent = DeferredForeignKey('parent_model', related_name='tags')
class Meta:
abstract = True
# Later on
class MyModel(models.Model):
title = models.CharField(max_length=100)
class MyTag(construct(AbstractTag, parent_model=MyModel)):
pass
Due to how Django works the implementation involves a touch of witchery so
should you absolutely hate it, you can still reconstruct the field as usual as
Django remains completely unaware of the deferred fields:

.. code-block:: python
class MyTag(AbstractTag):
parent = models.ForeignKey(MyModel, related_name='tags')
Magic Apps
----------

As much as we despise magic we also understand that it's important to provide
easy means to scaffold a working application. Satchless does not provide any
concrete models so getting started involved a fair share of work on your part.

To lower the barrier of entry we provide *MagicApps* that will take care of all
the model creation and let you get your feet wet without the risk of tripping.
*MagicApps* are flexible enough to allow you to override particular models while
having the rest of them constructed automatically. Please note however that we
do not encourage you to use *MagicApps* in a ready product as they are a hack
at best and subject to various limitations.

One important limitation you should be aware of is that *you can never have
more than one instance of the same MagicApp in the project*. This is because of
how Django register models and it's not something we plan to work around.


Domain driven models
--------------------

Main concepts behind Satchless models:

* No *one-fits-all* approach
* Single python class describes single class of products

If you already have some experience with other e-commerce platforms the above
statements might not sound and feel that natural at first glance
so let us draw some background behind them first. Most of the frameworks that we
came across in the past took quite the opposite direction.

Platforms like Satchmo, LFS or Oscar built their tightly coupled architectures
around a single Product model representing any of the products. Unfortunately,
even if this seems an obvious and handy choice it’s not likely to be the best
one in our opinion.

What we learnt is that the product’s model designed this way gets quickly
extremely inefficient and makes life harder in almost every aspect of further
development. It is especially true in case of custom, domain-driven e-commerce
solutions required to deal with millions of products and requests per day.


EAV vs Static classes
^^^^^^^^^^^^^^^^^^^^^

Let's talk about EAV approach first. It's evil.

When designing Product’s model around the “classic” concept you typically
use a single Product model, with a ProductClass and an Entity-Attribute-Value
approach to allow different kinds of products. Theoretically it allows to
create new kinds of products on the fly ie. via admin panel. Concern the
following issues introduced by this approach:
--------

* Despite creating new types of product through the admin, it’s very likely
you will still want to provide product class-specific templates and
logic like ie. variant forms.
* The database structure for products gets complicated, which slows
down even queries that might look (and should be) very simple
at first glance. It might make data-intensive operations like
import or migration tasks very time-consuming and complicated.
* It's ugly. EAV sucks and we know it.
Satchless is a low-level library that provides base classes, interfaces and patterns to work with while implementing a store. Its goal is to provide you with well-tested core logic to build business logic and UIs upon.

Basically, the main argument in favour of this approach is that it allows new
fields to be added quickly. But in practice it doesn't work out this way at all.
Satchless is **not a framework** and it will not give you a full-fledged store to work with. If that is what you want and you're working with Django, check the `Saleor <http://github.com/mirumee/saleor>`_ project instead.

**In Satchless we use model inheritance and have different product classes
treated as real python classes instead.**
.. toctree::
:maxdepth: 2
:numbered:

* Static classes are good and everyone knows how to work with them.
* One additional database table per product class, unless they need
some new foreign key relationships.
* Easier to do special logic on a per-class basis. Using the EAV
approach, this will involve a whole new level of models, making the
situation even worse.
* Easier to work with data migration tasks.
* No longer depend on fixtures to make the site work.
modules.rst
Loading

0 comments on commit 4fc3a87

Please sign in to comment.