Initial Installation and Configruation of Satchmo
This note documents my install of the current release of Satchmo, 0.9.2. Satchmo is an e-commerce platform built on top of Django, a python-based web framework.
I am a Django journeyman, but a Satchmo newb. Expect a few holes and/or inaccuracies in these notes w.r.t. Satchmo.
At the moment, I find some of the Satchmo terminology vague and/or used in a confusing manner. In particular, what exactly are stores, localsites, and apps. How do they relate to my planned implementation of an ecommerce site? The answers are not easily found. I have written a separate note about that. Since I am still, at the moment confused, it is inevitable that some of that confusion will spill over into these notes. You have been warned.
Intro & Resources
There apparently is no documentation for 0.9.2. At the time of this writing, you can choose between either:
- The current dev documentation (0.9.3) http://www.satchmoproject.com/docs/dev/
- Or the most recent "released" documentation (0.9.1) http://satchmoproject.sadba.org/docs/rel/latest/ which is also available in PDF format at http://cdn.bitbucket.org/chris1610/satchmo/downloads/Satchmo-0-9-1.pdf
Also, Bruce Kroeze (apparently a Satchmo developer) has a couple of helpful pages, but they are misformatted and possibly out of date. Regardless, they provide a few essential hints, which form the basis for these notes:
- Basic directory structure: http://gosatchmo.com/2010/starting-a-new-store-real-world-project-layout/
- Using templates: http://gosatchmo.com/2008/how-to-skin-a-satchmo-store-overriding-templates/
Prerequisites
It is not required, but I always use and strongly recommend both Ian Bicking's virtualenv and Doug Hellman's virtualenvwrapper.
pip, which is used to install the software is supplied by installing either virtualenv or easy_install (I do not recommend use of easy_install, although at least one set of offical Satchmo instructions show its use).
Installing Satchmo
There are multiple versions of Satchmo install instructions. It is difficult to determine which is authoritative (or the newest). They have needlessly muddied the waters. I assume that you are installing the current release (0.9.2).
1. Install the Python Imaging Library, if you don't have it already.
pip install PIL
2. Install Satchmo.
pip install satchmo==0.9.2
This article assumes that Satchmo has been installed in the directory $S. If you are using virtualenvwrapper, your $S will look something like /Users/cojones/.virtualenvs/proj1/src/satchmo.
Testing the Base Install
Sanity Test
To make an initial sanity test of the installation, type the following at the command line:
$ python Python 2.5.2 (r252:60911, Mar 12 2008, 13:39:09) [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import django >>> import satchmo_store >>> satchmo_store.get_version() '0.9-pre hg-YYYY:ZZZZZZZZZZ'
If that works, then the basics of the install are ok.
Test the Simple Store
Satchmo comes with a basic simple example store that you can use to verify your installation. We'll use it to perform a slightly more rigorous test of the installation.
During Satchmo installation, the clonesatchmo.py script is placed in your shell's search path. In an empty directory, run the script without arguments. It will create a directory named store, which will contain numerous files and subdirectories.
Note: clonesatchmo.py apparently does not play well with virtualenvs. If you are using them and run clonesatchmo with no args and get an error, re-run it in the following manner: clonesatchmo.py --skel $S/satchmo/projects/skeleton.
clonesatchmo.py does three things:
1. It looks for $S/satchmo/projects/skeleton, which is a minimal application layout. It also checks to ensure that a localsite directory exists within skeleton. If everything is OK, it will copy skeleton to the current directory and rename it store.
2. It customizes the configuration data in the newly created store.
3. It loads some initial store (and other) data into the DB and copies some static files.
After running clonesatchmo, run the following commands:
cd store ./manage.py runserver
This will start Django's internal web server. Test the simple store by going to http://localhost:8000. If that works, move on to the next section.
Initial Site
clonesatchmo creates (clones/copies) the skeleton and simple sites from the Satchmo source to create a basic Satchmo/Django app for you to use as the basis of your new site. The site that it creates (assuming the defaults were used) looks like this:
store ----> __init__.py local_settings.py localsite ----------> __init__.py manage.py models.py satchmo.log urls.py settings.py views.py simple.db static -------------> css ------> ... templates ---\ images ---> ... urls.py | js -------> ... | | \------> shop -----> email ---> ... pdf -----> ...
Note that both store and store/localsite are Django apps. Let's assume that we ran clonesatchmo in /Users/cojones/example, making the path to the above tree /Users/cojones/example/store. We'll refer to /Users/cojones/example as $E in this document.
Configure the Initial Site
This assumes that you ran clonesatchmo with the defaults. This more or less follows Bruce Kroeze's suggestions (he does not use clonesatchmo):
-
Edit $E/store/settings.py and change the base URL to the localsite app:
ROOT_URLCONF='store.localsite.urls'
-
Edit $E/store/localsite/urls.py so that it contains only the following two lines:
from django.conf.urls.defaults import * from store.urls import urlpatterns
(Note: the second line above corrects what appears to be an error in Bruce's directions.)
-
In $E/store/settings.py, ensure that store.localsite is the last app in INSTALLED_APPS.
Per Bruce's directions, the bulk of your implementation should go in localsite.
I must disclose that I am currently confused as to why Bruce states that your changes/implementation go into localsite, yet he also provides directions regarding template overrides using $E/store/templates, not $E/store/localsite/templates. I'm sure it's for an obvious reason that I just don't get at the moment.
Install The Debug Toolbar
I strongly recommend that you install the Django Debug Toolbar because it is an excellent tool to use in helping to figure out, among other things, which templates are being used in rendering a page.
A somewhat related side note -- if, in working on overriding templates, you find the local web server hanging, it is almost certainly due to a recursion that one of your recent template changes introduced. Back out your change, check your paths and override structure, and try again.
Customization
Let's test a couple of simple customizations to convince ourselves that our configuration will work going forward. This section assumes the default application structure created by clonesatchmo.
Customization One
By default, the store footer says Powered by Satchmo. Let's change that to say Modified June 3, 2012.
If we explore the Satchmo source that was installed in $S, we'll find that the footer is defined in the HTML template fragment:
in the file $S/apps/satchmo_store/shop/templates/base.html. The template is somewhat complicated contains much more than just the above code; we are only showing the portion of the code that defines the footer.
We also see that $S/apps/satchmo_store/shop/templates/shop/base.html contains the following:
{% extends "base.html" %} {# override this template if you want your shop template to be different than your base template #}
This is the complete contents of the file. It exists solely to give us a hint as to where we should make our overrides -- we should make them here (i.e., in shop/base.html), but within our application's directory structure, not in the Satchmo source.
So, to override the footer behavior, we'll have to create $E/store/templates/shop/base.html with the following contents:
{% extends "base.html" %} {# override this template if you want your shop template to be different than your base template #} {% block footer %} Modified June 3, 2012. {% endblock footer %}
Although it will be clear that the change worked, it will be interesting to use the Debug Toolbar to inspect the template path as well as to see the other templates that were loaded. In fact, rather than a somewhat blind search of $S, the Toolbar is the best way to quickly determine which template(s) need to be overridden when you want to customize behavior.
Customization Two
You will have some sample products in the store created by clonesatchmo. Go to your store and click on Science Fiction in Book Categories. Click on the book Robots Attack!. This particular book is setup as a configurable product within Satchmo. Below the price is the statement 'Please choose your options:'. Let's change that to 'Please carefully choose your options:'. We will ignore translations into other languages for this example.
Using the Toolbar, you can see that the relevant template is $S/apps/product/templates/product/detail_configurableproduct.html.
There aren't many blocks within the template, which means that we'll have to replicate a substantial portion of the template, just to change the wording.
Create the directory $E/store/templates/product and copy the detail_configurableproduct.html file there. Edit the file to add the additional word. Specifically,
<p>{% trans "Please choose your options" %}:</p>
will become
<p>{% trans "Please carefully choose your options" %}:</p>
If you reload the page, you'll see your change appear.
Customization Three
There was something about the last customization that was distasteful. Namely, we copied the entire file just to change one word. Yes, there are only a couple of blocks that we could attempt to override, so some duplication is unavoidable, but shouldn't we get rid of what duplication that we can? OK, let's try.
Based on my understanding of Django templates, the best we can hope for is to get rid of everything but the productdetail block. It's not a huge difference, but let's try it. That would mean that $E/store/templates/product/detail_configurableproduct.html should look something like this:
{% extends "product/detail_configurableproduct.html" %} {% load i18n %} {% load thumbnail %} {% load satchmo_price %} {% load satchmo_util %} {% load satchmo_currency satchmo_category%} {% load satchmo_discounts satchmo_tax %} {% load app_plugins %} {% load satchmo_thumbnail %} {% block productdetail %} {% begin comment %} Duplicated code removed for clarity. In your version of this file, you will have to include all the code I removed. {% end comment %} {% if options %} {# Here is our change #} <p>{% trans "Please carefully choose your options" %}:</p> {% endif %} {% begin comment %} Duplicated code removed for clarity. In your version of this file, you will have to include all the code I removed. {% end comment %} {% endblock productdetail %}
If you try this, your server will hang when you view the page. Why? Clearly, there is recursive template inclusion with no termination.
The bottom line is that I don't know how to do this particular override. It seems clear that we need to override $S/apps/product/templates/product/detail_configurableproduct.html, thus the first line of the file above. However, it appears that the directive actually causes the template engine to keep including the file we modified, namely $E/store/templates/product/detail_configurableproduct.html. This is a Django issue, not a Satchmo issue. How does one handle this? The only thing I can think of off the top of my head is to:
- Create a new template for this purpose, with a different name, let's call it detail_configurableproduct_extended.html. I'll refer to it as dce.html just to keep things short.
- dce.html would contain the template code above.
- The relevant view would have to be modified to use dce.html instead of dc.html.
- Under this scheme, $E/store/templates/product/detail_configurableproduct.html would not exist or be used.
This seems to allow dce.html to extend product/detail_configurableproduct.html without risk of recursion. But this approach is ugly. Surely I'm missing something fundamental here.
After some searching, I see that the recursion issue mentioned here has been discussed extensively. Until there is a native way within Django to avoid the recursion, it seems that most people just copy the template as I did in example two, distasteful as that may be.