558 lines
21 KiB
ReStructuredText
558 lines
21 KiB
ReStructuredText
===================================
|
|
Howto: build a website with OpenERP
|
|
===================================
|
|
|
|
.. queue:: howto_website/series
|
|
|
|
.. warning::
|
|
|
|
This guide assumes `basic knowledge of python
|
|
<http://docs.python.org/2/tutorial/>`_.
|
|
|
|
This guide assumes :ref:`an OpenERP installed and ready for development
|
|
<getting_started_installation_source-link>`.
|
|
|
|
For production deployment, see the dedicated guides :ref:`using-gunicorn`
|
|
and :ref:`using-mod-wsgi`.
|
|
|
|
Creating a basic module
|
|
=======================
|
|
|
|
In OpenERP, doing things takes the form of creating modules, and these modules
|
|
customize the behavior of the OpenERP installation. The first step is thus to
|
|
create a module: at the command-line, go to your server's directory and enter
|
|
|
|
.. code-block:: console
|
|
|
|
$ ./oe scaffold Academy ../my-modules
|
|
|
|
This will build a basic module for you in a directory called ``my-modules``
|
|
right next to your server's directory:
|
|
|
|
.. code-block:: text
|
|
|
|
academy
|
|
├── __init__.py
|
|
├── __openerp__.py
|
|
├── controllers
|
|
│ ├── __init__.py
|
|
│ └── academy.py
|
|
├── models
|
|
│ ├── __init__.py
|
|
│ └── academy.py
|
|
└── security
|
|
└── ir.model.access.csv
|
|
|
|
* ``academy`` is the root directory of your module
|
|
* ``__init__.py`` tells Python that it is a valid package, and imports
|
|
sub-packages and sub-modules
|
|
* ``__openerp__.py`` provides various meta-information about your module to
|
|
OpenERP (a short description, the module's dependencies, its author, its
|
|
version, ...)
|
|
* ``controllers`` holds the object responding to web (browser) requests
|
|
- ``academy.py`` is where a default controller has been created for you
|
|
* ``models`` holds OpenERP stored objects, ignore it for now, we'll dive into
|
|
it when `storing data in OpenERP`
|
|
* ``ir.model.access.csv`` defines basic access rights to the models, you can
|
|
also ignore it for now
|
|
|
|
.. patch::
|
|
:hidden:
|
|
|
|
Now we can create a database, start your OpenERP server and install your new
|
|
module in it:
|
|
|
|
.. code-block:: console
|
|
|
|
$ createdb academy
|
|
$ ./openerp-server --addons-path=../web/addons,../addons,../my-modules \
|
|
-d academy -i academy --db-filter=academy
|
|
|
|
* ``--addons-path`` tells OpenERP where it can find its modules. By default it
|
|
will only look into ``openerp/addons``, this adds the web client modules,
|
|
the "standard" business modules (not needed yet) and the place where your
|
|
own ``academy`` module lives.
|
|
* ``-i`` installs the provided module name in the database specified via
|
|
``-d``
|
|
* ``--db-filter`` means the specified database will be selected by default in
|
|
the web interface, and will be the only one selectable (makes starting
|
|
things up simpler)
|
|
|
|
Once the installation is finished you should see ``HTTP service (werkzeug)
|
|
running on 0.0.0.0:8069`` and nothing more happening in the log. You can now
|
|
open a web browser and navigate to http://localhost:8069. A page should
|
|
appear with just the words "Hello, world!" on it:
|
|
|
|
.. image:: howto_website/helloworld.png
|
|
|
|
This page is generated by the ``index`` method in
|
|
:file:`academy/controllers/academy.py`, which just returns some text. Let's
|
|
make it prettier by returning HTML and using bootstrap_ to get a nicer default
|
|
rendering:
|
|
|
|
.. patch::
|
|
|
|
Restart the server, refresh the page
|
|
|
|
.. image:: howto_website/hellobootstrap.png
|
|
|
|
Although it is subtle for so little text and markup, the font has changed and
|
|
margins have been added to the page.
|
|
|
|
.. note::
|
|
|
|
this example requires internet access as we're accessing a :abbr:`CDN
|
|
(Content Delivery Network, large distributed networks hosting static files
|
|
and trying to provide high-performance and high-availability of these
|
|
files)`-hosted file.
|
|
|
|
.. note::
|
|
|
|
At this point, the OpenERP server has no autoreloader. Every time you
|
|
Python code (and later templates or data files), you should restart the
|
|
server using the original startup instruction (without the re-creation of
|
|
the database)
|
|
|
|
Controller Parameters
|
|
=====================
|
|
|
|
For dynamic pages, query parameters are passed as string parameters to the
|
|
controller method. For instance the index page can display a list of teaching
|
|
assistants, and link to each assistant's page using an index (in a global
|
|
array for now):
|
|
|
|
.. patch::
|
|
|
|
No validation is performed on query input values, it could be missing
|
|
altogether (if a user accesses ``/tas/`` directly) or it could be incorrectly
|
|
formatted. For this reason, query parameters are generally used to provide
|
|
"options" to a given page, and "required" data tends (when possible) to be
|
|
inserted directly in the URL.
|
|
|
|
This we can do by adding `converter patterns`_ to the URL in ``@http.route``:
|
|
|
|
.. patch::
|
|
|
|
These patterns will generally do some validation (e.g. if the ``id`` is not
|
|
a valid integer the converter will result in a ``404 Not Found`` page instead
|
|
of a 500 server error when the conversion failed in our own code) and may
|
|
perform some parsing or type conversion (in this case the conversion from a
|
|
URL section — a string — to a Python integer).
|
|
|
|
Basic templates
|
|
===============
|
|
|
|
So far we've output HTML by munging strings. It works, but is not exactly fun
|
|
to edit (and somewhat unsafe to boot) as even advanced text editors have a
|
|
hard time understanding they're dealing with HTML embedded in Python code.
|
|
|
|
The usual solution is to use templates_, documents with placeholders which can
|
|
be "rendered" to produce final pages (or others). OpenERP lets you use any
|
|
Python templating system you want, but bundles its own :doc:`QWeb
|
|
</06_ir_qweb>` templating system which we'll later see offers some useful
|
|
features.
|
|
|
|
Let's move our 2 pseudo-templates from inline strings to actual templates:
|
|
|
|
.. patch::
|
|
|
|
This simplifies the controller code by moving data formatting out of it, and
|
|
generally makes it simpler for designers to edit the markup.
|
|
|
|
.. todo:: link to section about reusing/altering existing stuff, template
|
|
overriding
|
|
|
|
.. _howto-website-support:
|
|
|
|
OpenERP's Website support
|
|
=========================
|
|
|
|
OpenERP 8 is bundled with new modules dedicated specifically to building
|
|
websites (whether it be simply sets of pages or more complex components such
|
|
as blogs).
|
|
|
|
First, we'll install the ``website`` module: restart your server with
|
|
|
|
.. code-block:: console
|
|
|
|
$ ./openerp-server --addons-path=../web/addons,../addons,../my-modules \
|
|
-d academy -i website --db-filter=academy
|
|
|
|
.. todo:: is it possible that the page has *not* been replaced?
|
|
|
|
If you navigate to `your openerp`_, your basic page has now been replaced by
|
|
the generic empty index page. Because you are not logged-in yet, the page has
|
|
no content and just basic placeholders in the header and footer. Click on the
|
|
:guilabel:`Sign In` link, fill in your credentials (``admin``/``admin`` by
|
|
default), click :guilabel:`Log in`.
|
|
|
|
You're now in OpenERP "proper", the backend/administrative interface. We'll
|
|
deal with it in :ref:`a latter section <howto-website-administration>`. For
|
|
now, click on the :menuselection:`Website` menu item in the top-left of the
|
|
browser, between :menuselection:`Messaging` and :menuselection:`Settings`.
|
|
|
|
You're back to your website, but are now an administrator and thus have access
|
|
to the advanced edition features of an OpenERP-built website. Let's quickly
|
|
run through them.
|
|
|
|
Mobile Preview
|
|
--------------
|
|
|
|
.. todo:: insert menu bar, mobile preview icon outlined
|
|
|
|
Because the OpenERP website system is built with bootstrap_, it is easy to
|
|
build "responsive" websites reacting to the size of the screen and making best
|
|
use of the available space.
|
|
|
|
The mobile preview does not give you the exact rendering of a smartphone (if
|
|
there's such a thing), but it goes some of the way and lets you know if it's
|
|
completely unusable without having to actually switch to a smartphone and try
|
|
to find out how to see your site with it (especially during edition).
|
|
|
|
.. todo:: screenshot of page in desktop v mobile preview layout
|
|
|
|
Promote
|
|
-------
|
|
|
|
Lets you easily configure how your page should advertise its existence to
|
|
search engines: keywords matching the page's subject, nice titles and
|
|
descriptions for visitors finding the page via search engines.
|
|
|
|
.. todo:: screenshot promote
|
|
|
|
Content
|
|
-------
|
|
|
|
The content menu provides "top level" operations: manipulation of the main
|
|
menu (creation of new links, submenus, etc...) and creation of high-level
|
|
objects. At the moment only pages (they're the top-level object for the
|
|
``website`` module), but installing the recruitment module will add an entry
|
|
to quick-create a new job offer, and the events module one for a new event.
|
|
|
|
Customize
|
|
---------
|
|
|
|
The customize menu provides a number of loosely associated features, broadly
|
|
split in two sections:
|
|
|
|
Templates configuration
|
|
```````````````````````
|
|
|
|
Some templates provide alternative versions/structures. These alternative
|
|
version can be toggled from the template configuration checkboxes. Two of
|
|
these are bundled in ``website``, providing an alternative blank footer to
|
|
fill, and the other one replacing your company's name by your company's logo
|
|
in the navigation bar.
|
|
|
|
Theming
|
|
```````
|
|
|
|
As previously mentioned, OpenERP's website module uses bootstrap_ for much of
|
|
its basic styles and layout. This, in turns, allows using existing bootstrap
|
|
themes to alter the color scheme of your website.
|
|
|
|
:menuselection:`Customize --> Change Theme` opens a picker to a few bundled
|
|
Bootstrap themes, and lets you change the look of your site quickly and
|
|
on-the-fly.
|
|
|
|
.. todo:: creating or installing new boostrap themes?
|
|
|
|
HTML Editor
|
|
```````````
|
|
|
|
Opens a full-blown code editor on the current template, and lets you easily
|
|
edit templates in-place, either for a quick fix which is simpler to perform in
|
|
code yet from the page, or to try things out before moving them to template
|
|
files.
|
|
|
|
Help
|
|
----
|
|
|
|
Lists available tutorials, step-by-step lessons in using the website.
|
|
``website`` only provides :menuselection:`Help --> Insert a banner` which
|
|
shows some basic features of the website (snippets, edition, mobile preview)
|
|
while guiding the user through. Other modules can provide additional tutorials
|
|
for their advanced features.
|
|
|
|
Edit
|
|
----
|
|
|
|
Starts up the rich text editor, which lets you alter page text, add links and
|
|
images, change colors, etc…
|
|
|
|
Snippets
|
|
````````
|
|
|
|
:guilabel:`Insert Blocks` opens the snippets UI: pre-built layout blocks which
|
|
you can then fill with your own content (text, pictures, …). Simply select a
|
|
snippet and drag-and-drop it on your page. Guides should appear when you start
|
|
dragging a snippet, showing where the snippet can be dropped.
|
|
|
|
Building your pages with OpenERP Website
|
|
========================================
|
|
|
|
As we've seen, your index page has "disappeared" and been replaced by the one
|
|
provided by ``website``. The page is not lost, but because ``website`` was
|
|
installed after the ``academy`` module, its index page takes over routing (two
|
|
index pages exist, and one is picked over the other).
|
|
|
|
To fix the issue, we can simply add ``website`` as a dependency to ``academy``
|
|
(that is, tell OpenERP that ``academy`` needs ``website`` to work correctly):
|
|
|
|
.. needs -u all to update metadata
|
|
|
|
.. patch::
|
|
|
|
This will cause ``academy``'s index page to overwrite ``website``'s.
|
|
|
|
Reload `your openerp`_. Your old index page is back.
|
|
|
|
However, none of the website edition tools are available. That is because much
|
|
of these tools are inserted and enabled by the website layout template. Let's
|
|
use that layout instead of our own page structure:
|
|
|
|
.. patch::
|
|
|
|
* ``website.layout`` is the main Website layout, it provides standard headers
|
|
and footers as well as integration with various customization tools.
|
|
|
|
* there's quite a bit of complex markup, used as hooks for various features
|
|
(e.g. snippets). Although technically not mandatory, some things will not
|
|
work if they're not there.
|
|
|
|
* if you go in the HTML editor (:menuselection:`Customize --> HTML Editor`),
|
|
you can see and edit your template
|
|
|
|
.. todo:: website template generator
|
|
|
|
If you try to add content to the TA pages using snippets, for instance insert
|
|
an :guilabel:`image-text` snippet to add a picture and a short biography for a
|
|
TA, you'll notice things don't work right: because snippets are added in the
|
|
template itself, they're content which is the same across all pages using that
|
|
template.
|
|
|
|
Thus snippets are mostly for generic content, when a given template is only
|
|
used for a single page, or to add content in HTML fields.
|
|
|
|
.. note::
|
|
|
|
When creating a new page (e.g. via :menuselection:`Content --> New Page`),
|
|
OpenERP will duplicate a "source" template, and create a new template for
|
|
each page. As a result, it's safe to use dedicated-content snippets for
|
|
"static" pages.
|
|
|
|
Time, then, to create more specific content.
|
|
|
|
Storing data in OpenERP
|
|
=======================
|
|
|
|
The conceptual storage model of OpenERP is simple: there are storage tables,
|
|
represented by OpenERP models, and inside these tables are records. The first
|
|
step, then, is to define a model.
|
|
|
|
We'll start by moving our teaching assistants in the database:
|
|
|
|
.. patch::
|
|
|
|
We've also altered the index method slightly, to retrieve our teaching
|
|
assistants from the database instead of storing them in a global list in the
|
|
module\ [#taprofile]_.
|
|
|
|
.. note:: :file:`ir.model.access.csv` is necessary to tell OpenERP that any
|
|
user can *see* the teaching assistants: by default, only the
|
|
administrator can see, edit, create or destroy objects. Here, we
|
|
only change the ``read`` permission to allow any user to list and
|
|
browse teaching assistants.
|
|
|
|
.. todo:: command/shortcut
|
|
|
|
Update the module, reload `your openerp`_… and the Teaching Assistants list is
|
|
empty since we haven't put any TA in the database.
|
|
|
|
Let's add them in data files:
|
|
|
|
.. patch::
|
|
|
|
Update the module again, reload `your openerp`_ and the TAs are back. Click on
|
|
a TA name, and you'll see an error message. Let's fix the TA view now:
|
|
|
|
.. todo:: if ta template was modified in previous section, it's marked
|
|
noupdate and updating the module will have no effect for no known
|
|
reason. That's really quite annoying.
|
|
|
|
.. patch::
|
|
|
|
There are a few non-obvious things here, so let's go through them for clarity:
|
|
|
|
* OpenERP provides a has a special `converter pattern`_, which knows how to
|
|
retrieve OpenERP objects by identifier. Instead of an integer or other
|
|
similar basic value, ``ta`` thus gets a full-blown ``academy.tas`` object,
|
|
without having to retrieve it by hand (as is done in ``index``).
|
|
|
|
* However because the ``model()`` `converter pattern`_ takes an identifier, we
|
|
have to alter the creation of ``ta``'s URL to include such an identifier,
|
|
rather than an index in an array
|
|
|
|
* Finally, ``website.render()`` wants a dict as its rendering context, not an
|
|
object, which is why we wrap our ``ta`` object into one.
|
|
|
|
We're still where we started this section though: if we add snippets to or
|
|
edit the text of a TA's page, these editions will be visible across all TA
|
|
pages since they'll be stored in the shared ``academy.ta`` template.
|
|
|
|
Not only that, but we can not even edit the TA's name, even though it's not
|
|
shared content.
|
|
|
|
Let's fix that first, instead of using the basic "display this content"
|
|
template tag ``t-esc``, we'll use one aware of OpenERP objects and their
|
|
fields:
|
|
|
|
.. patch::
|
|
|
|
Update the module, go into a TA page and activate the edition mode. If you
|
|
move your mouse over the TA's name, it is surrounded by a yellow border, and
|
|
you can edit its content. If you change the name of a TA and save the page,
|
|
the change is correctly stored in the TA's record, the name is fixed when you
|
|
go to the index page but other TAs remain unaffected.
|
|
|
|
For the issue of customizing our TA profiles, we can expand our model with a
|
|
"freeform" HTML field:
|
|
|
|
.. patch::
|
|
|
|
Then, insert the new biographical content in the template using the same
|
|
object-aware template tag:
|
|
|
|
.. patch::
|
|
|
|
.. todo:: updating the ``name`` field from the RTE altered the template, which
|
|
locked it...
|
|
|
|
Update the module, browse to a TA's page and open the edition mode (using the
|
|
:guilabel:`Edit` button in the window's top-right). The empty HTML field now
|
|
displays a big placeholder image, if you drop snippets in or write some
|
|
content for one of the teaching assistants, you will see that other TA
|
|
profiles are unaffected.
|
|
|
|
A more complex model
|
|
--------------------
|
|
|
|
Up to now, we've been working with displaying and manipulating objects
|
|
representing teaching assistants. It's a basic and simple concept, but not one
|
|
which allows for much further diving into interesting tools of OpenERP.
|
|
|
|
We need an object fitting the theme yet allowing for richer interactions and
|
|
more interesting extensions. Course lectures seem to fit: they can be
|
|
displayed in various manners (e.g. as a list of lectures or as a calendar),
|
|
they can be moved around as necessary (cancelled/rescheduled), they can have
|
|
numerous pieces of data attached both intrinsic (lecture transcripts) and
|
|
extrinsic (attendance records, student discussions, etc…).
|
|
|
|
.. patch::
|
|
|
|
.. TODO:: ``-u`` did not work, not even ``-uall``, new data file does not get
|
|
installed
|
|
|
|
Note a new feature: ``t-field`` tags can take options through
|
|
``t-field-options``. The options must be a JSON_ object. Available options
|
|
depend on the field's type and potentially the display widget (some types
|
|
of fields can be displayed in multiple manners). In this case, the same
|
|
``date`` field is displayed using custom date formats, one being the generic
|
|
``long`` (which depends on the current user's locale) and the other being
|
|
an explicit format for `the weekday in short form
|
|
<http://babel.pocoo.org/docs/dates/#date-fields>`_.
|
|
|
|
.. note:: in edition mode, formatted date and datetime fields revert to a
|
|
canonical representation in order to provide all of the field's
|
|
information.
|
|
|
|
.. warning:: if you edit the course's dates, you will notice that the two
|
|
displays of the ``date`` field are unlinked, if one is edited
|
|
the second one will not change until the edition is saved. This
|
|
is a limitation of the current ``website`` but may be improved in
|
|
future releases.
|
|
|
|
.. sending & storing comments (?)
|
|
|
|
.. _howto-website-administration:
|
|
|
|
Administration and ERP Integration
|
|
==================================
|
|
|
|
In practice, the data we've created so far using XML data files is usually
|
|
stored as "demo data", used for testing and demonstrations of modules, and the
|
|
actual user data is input via the OpenERP "backend", which we're going to try
|
|
out now. First let's move our data set to demo data:
|
|
|
|
.. patch::
|
|
|
|
the difference is simply that new databases can be created either in "demo"
|
|
mode or in "no demo" mode. In the former case, the database will be preloaded
|
|
with any demo data configured in the installed module.
|
|
|
|
.. todo:: need to create a new DB again?
|
|
|
|
A brief and incomplete introduction to the OpenERP administration
|
|
-----------------------------------------------------------------
|
|
|
|
You've already seen it for a very short time in :ref:`howto-website-support`,
|
|
you can go back to it using :menuselection:`Administrator --> Administration`
|
|
if you're already logged-in (which you should be), or go through
|
|
:menuselection:`Sign In` again if you are not.
|
|
|
|
The conceptual structure of the OpenERP backend is simple:
|
|
|
|
1. first are menus, menus are a tree (they can have sub-menus). To menus
|
|
without children is mapped…
|
|
|
|
2. an action. Actions have various types, they can be links, reports (PDF),
|
|
code which the server should execute or window actions. Window actions
|
|
tell the client to display the OpenERP object according to certain views…
|
|
|
|
3. a view has a type, the broad category to which it corresponds (tree, form,
|
|
graph, calendar, …) and its architecture which represents the way the
|
|
object is laid out inside the view.
|
|
|
|
By default, when an OpenERP object is *defined* it is essentially invisible in
|
|
the interface. To make it visible, it needs to be available through an action,
|
|
which itself needs to be reachable somehow, usually a through a menu.
|
|
|
|
Let us, then, create a menu and an action for our lectures:
|
|
|
|
.. patch::
|
|
|
|
.. todo:: reinstall module? update?
|
|
|
|
If you reload the backend, you should see a new menu :menuselection:`Academy`
|
|
at the top-left corner, before :menuselection:`Messaging`. In it is the
|
|
submenus we defined via ``menuitem``, and within (the first submenu is
|
|
selected by default) opens a list view of the lectures. To the right is a
|
|
series of 2 buttons, which lets you toggle between the "list" view (overview
|
|
of all records in the object) and the "form" view (view an manipulation of a
|
|
single record). The :guilabel:`Create` button above the list lets you create
|
|
new record, you can select records to delete them.
|
|
|
|
There's one big issue to fix right now, the labeling of the column in the list
|
|
and the fields in the form view, which are all currently :guilabel:`unknown`:
|
|
|
|
.. FIXME fix labels
|
|
|
|
.. create menu, action
|
|
.. improve generated views
|
|
.. create list & form views for events
|
|
|
|
.. [#taprofile] the teaching assistants profile view ends up broken for now,
|
|
but don't worry we'll get around to it
|
|
|
|
.. _bootstrap: http://getbootstrap.com
|
|
|
|
.. _converter pattern:
|
|
.. _converter patterns:
|
|
http://werkzeug.pocoo.org/docs/routing/#rule-format
|
|
|
|
.. _templates: http://en.wikipedia.org/wiki/Web_template
|
|
|
|
.. _your openerp: http://localhost:8069/
|
|
|
|
.. _JSON: http://www.json.org
|